home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / pcmagazi / 1989 / 18 / menu.asm < prev    next >
Assembly Source File  |  1989-08-12  |  135KB  |  3,133 lines

  1.                 PAGE    66,132          ;
  2.                 NAME    MENU            ;
  3.                 TITLE   Menu utility    ;
  4. ;
  5. ; MENU provides a screen oriented interface for use in constructing batch files
  6. ; using menu selection and fill-in-the-blanks approaches.
  7. ;
  8. ; Use:
  9. ;
  10. ; MENU [/N/D/E] [screen] [template] [out out out ...]
  11. ;
  12. ; "screen" is the display file that the user sees.  "screen" contains the text
  13. ; to be displayed, the display attributes, and display management commands.
  14. ; The logical screen may be longer than a physical screen.
  15. ;
  16. ; "template" is a file that defines the format of the output file "out".
  17. ; "template" consists of the exact text to be sent to "out" except for the
  18. ; inclusion of bracketed references.  Text of the form [nnn] is replaced by
  19. ;
  20. ; "out" is the name of the file to receive the final output.  Multiple out
  21. ; files may be specified.
  22. ;
  23. ; Copyright (c) 1989 Ziff Communications Co.
  24. ; Written  May 1989 for PC Magazine by Ronald Q. Smith
  25. ;
  26. ; Constant definitions.
  27. ;
  28. ; DOS Interface
  29. ;
  30. DOS$            EQU     21H             ; DOS function call INT
  31. ; Function values for DOS$
  32. DATE$           EQU     2AH             ; Get date
  33. TIME$           EQU     2CH             ; Get time of day
  34. CREATE$         EQU     3CH             ; Create file
  35. OPEN$           EQU     3DH             ; Open file
  36. CLOSE$          EQU     3EH             ; Close file
  37. RDFILE$         EQU     3FH             ; Read file
  38. WRFILE$         EQU     40H             ; Write file
  39. EXIT$           EQU     4CH             ; Return to DOS
  40. STDIN           EQU     0               ; Standard input handle
  41. STDOUT          EQU     1               ; Standard output handle
  42. ERROUT          EQU     2               ; Handle for error messages
  43. ;
  44. ; BIOS Interface
  45. ;
  46. VIDEO$          EQU     10H             ; CRT handler INT
  47. ; Function values for VIDEO$
  48. SMODE$          EQU     0               ; Set video mode
  49. CRS$            EQU     2               ; Set cursor position function
  50. RDCRS$          EQU     3               ; Read cursor position function
  51. PAGE$           EQU     5               ; Set video page
  52. RACH$           EQU     8               ; Read attribute and character
  53. WACH$           EQU     9               ; Write attribute and character
  54. WCHR$           EQU     10              ; Write character
  55. VIDSTAT$        EQU     15              ; Get current video state
  56. EGASTAT$        EQU     17              ; Get EGA status
  57. ALTSEL$         EQU     18              ; Alternate select to EGA
  58. ;
  59. KYBD$           EQU     16H             ; Keyboard handler INT
  60. ;
  61. ; Non-printing ASCII characters
  62. ;
  63. BS_CHR          EQU     8               ; Back space
  64. TAB_CHR         EQU     9               ; Tab
  65. LF_CHR          EQU     10              ; Line feed
  66. CR_CHR          EQU     13              ; Carriage return
  67. EOF_CHR         EQU     26              ; End-of-file sentinel character
  68. ESC_CHR         EQU     27              ; Esc
  69. ;
  70. ; Screen constants.
  71. ;
  72. SCR_ATTR        EQU     7               ; White on black default
  73. MONO_SEG        EQU     0B000H          ; Monochrome adapter refresh segment
  74. COLOR_SEG       EQU     0B800H          ; Color/EGA adapter refresh segment
  75. ;
  76. ; I/O constants.
  77. ;
  78. L_INB           EQU     512             ; Input buffer size
  79. L_OUTB          EQU     512             ; Output buffer size
  80. EDIT_FLD        EQU     100             ; Maximum number of input fields
  81. ;
  82. ; BIOS Data segment
  83. ;
  84. BIOS_DATA       SEGMENT AT 40H          ;
  85.                 ORG     63H             ;
  86. ADDR_6845       DW      ?               ; I/O address of current display
  87.                 ORG     87H             ;
  88. EGA_INFO        DB      ?               ; EGA status byte
  89. EGA_MASK        EQU     00001000B       ; EGA active bit (0=active)
  90. BIOS_DATA       ENDS                    ;
  91. ;
  92. ; Macros.
  93. ;
  94. ; DBA creates character,attribute pairs from an attribute value (ATTR) and
  95. ; a string (STR).  This macro may be used to create values to be copied
  96. ; directly to the screen buffer.
  97. ;
  98. DBA             MACRO   ATTR,STR        ; DB with attribute
  99.                   IRPC    C,<&STR>      ;
  100.                     DB      '&C',ATTR   ;
  101.                   ENDM                  ;
  102.                 ENDM                    ;
  103. ;
  104. ; Start of program area.
  105. ;
  106. CODE            SEGMENT PARA PUBLIC     ;
  107.                 ASSUME  CS:CODE,DS:CODE,ES:CODE,SS:CODE ;
  108. ;
  109. ; Program Segment Prefix area.
  110. ;
  111. MENU_PSP        LABEL   BYTE            ; Start of segment
  112.                 ORG     80H             ;
  113. P_CNT           DB      ?               ; Number of bytes of parameter supplied
  114. P_CMD           DB      ?               ; Parameter area
  115. ;
  116. ; MENU Body
  117. ;
  118.                 ORG     100H            ;
  119. MENU            PROC                    ;
  120.                 JMP     INIT            ; Go to initialization code
  121. ;
  122. ; Data area.
  123. ;
  124. ;
  125. ; Screen handling.
  126. ;
  127. SAVEPAGE        DB      ?               ; Save video page
  128. SAVECRS         DW      ?               ; Save original cursor position
  129. FAST            DB      0               ; If non-zero, fast screen update
  130. VIDEO_SEG       DW      MONO_SEG        ; Default video display segment
  131. STATUS_REG      DW      ?               ; Video status register
  132. SCR_COL         DB      80,0            ; Default screen width
  133. SCR_LIN         DB      25,0            ; Default number of lines
  134. DISP_SIZE       DW      24*80*2         ; Default display area size
  135. DISP_LOC        DW      0FFFFH          ; Save area start for screen
  136. EDIT_LAST       DW      ?               ; Last address in edit buffer
  137. ATTRIBUTE       DB      SCR_ATTR        ; Current screen attribute
  138. DOPT            DW      L_SCHR          ; Length of screen character table
  139. EOPT            DW      L_KEYT          ; Length of editing character table
  140. SHOW            DB      0               ; Show fields if set
  141. SCRN_END        DW      ?               ; Location of end of screen
  142. ;
  143. ; Input field handling.
  144. ;
  145. EDIT_NUM        DW      0               ; Index to next input area def
  146. EDIT_AREA       DW      EDIT_FLD DUP(0,0) ; Start and end of input areas
  147.                 DW      0,0             ; Last DEF_AREA entry
  148. ;
  149. ; Constant fields.
  150. ;
  151. CONST_NUM       DW      0               ; Index to next constant definition
  152. CONST_AREA      DW      EDIT_FLD DUP(0,0) ; Start and end of constant areas
  153. ;
  154. ; Defining new input fields.
  155. ;
  156. DEF_NUM         DW      0               ; Index to next definition
  157. DEF_AREA        EQU     EDIT_AREA+4     ; Start and end of input areas
  158.                                         ; Only use one real input area
  159.                                         ; when defining new ones
  160. ;
  161. ; Handles and other I/O related.
  162. ;
  163. SCREENFILE      DW      ?               ; Screen file handle
  164. TEMPLFILE       DW      ?               ; Template file handle
  165. IN_CNT          DW      0               ; Characters remaining in input buffer
  166. IN_INDX         DW      ?               ; Next character in input buffer
  167. NUM_OUT         DW      0               ; Number of output files
  168. OUT_HNDL        LABEL   WORD            ;
  169.                 DW      64 DUP(0)       ; Output file handles
  170. OUTFILE         DW      ?               ; Current output file handle
  171. OUT_INDX        DW      0               ; Output buffer index
  172. ;
  173. ; Messages
  174. ;
  175. CRLF            DB      CR_CHR,LF_CHR   ;
  176. BIG_MSG         DB      "Screen file is too long." ;
  177. L_BIG           EQU     $-BIG_MSG       ;
  178. SCRN_ERR        DB      'Error reading screen file.' ;
  179. L_SERR          EQU     $-SCRN_ERR      ;
  180. INP_MSG         DB      "Screen file contains unbalanced []'s or too " ;
  181.                 DB      'many fields.'  ;
  182. L_INP           EQU     $-INP_MSG       ;
  183. CONST_MSG       DB      "Screen file contains unbalanced {}'s or too " ;
  184.                 DB      'many constants.' ;
  185. L_CONST         EQU     $-CONST_MSG     ;
  186. ANSI_MSG        DB      'Illegal ANSI (ESC) sequence.  Only ESC [#;...#m ' ;
  187.                 DB      'is allowed.  #=0-47.' ;
  188. L_ANSI          EQU     $-ANSI_MSG      ;
  189. TMPL_ERR        DB      'Error reading template file.' ;
  190. L_TMPL          EQU     $-TMPL_ERR      ;
  191. TMPL_MSG        DB      "Template file contains unbalanced []'s, {}'s, " ;
  192.                 DB      "<>'s or a bad field number." ;
  193. L_TBAD          EQU     $-TMPL_MSG      ;
  194. OUT_MSG         DB      'Error writing output file.' ;
  195. L_OUT           EQU     $-OUT_MSG       ;
  196. Q_MSG           DB      'Do you want to quit? YN' ;
  197. L_Q             EQU     $-Q_MSG         ;
  198. ROOM_MSG        DB      'Too many fields' ;
  199. L_ROOM          EQU     $-ROOM_MSG      ;
  200. BAL_MSG         DB      'No field start' ;
  201. L_BAL           EQU     $-BAL_MSG       ;
  202. NEST_MSG        DB      'Fields may not be nested' ;
  203. L_NEST          EQU     $-NEST_MSG      ;
  204. COLOR_MSG       DB      'Text='         ;
  205. TCLR            DB      '   Bkgr='      ;
  206. BCLR            DB      '  Blink='      ;
  207. BLNK            DB      ' '             ;
  208. L_COLOR         EQU     $-COLOR_MSG     ;
  209. ;
  210. ; Date and time values
  211. ;
  212. DOW             DW      0               ; Day of week index (0-6)*3
  213. MON             DW      0               ; Month index (0-12)*3
  214. MONTH           DW      'MM'            ; Month
  215. DAY             DW      'DD'            ; Day
  216. CENTURY         DW      'CC'            ; Century
  217. YEAR            DW      'YY'            ; Year
  218. HOUR            DW      'hh'            ; Hours
  219. MINUTE          DW      'mm'            ; Minutes
  220. SECOND          DW      'ss'            ; Seconds
  221. DOW_TAB         LABEL   BYTE            ; Day of week abbreviations
  222.                 DB      'Sun'           ;
  223.                 DB      'Mon'           ;
  224.                 DB      'Tue'           ;
  225.                 DB      'Wed'           ;
  226.                 DB      'Thu'           ;
  227.                 DB      'Fri'           ;
  228.                 DB      'Sat'           ;
  229. MON_TAB         LABEL   BYTE            ; Month abbreviations
  230.                 DB      'Jan'           ;
  231.                 DB      'Feb'           ;
  232.                 DB      'Mar'           ;
  233.                 DB      'Apr'           ;
  234.                 DB      'May'           ;
  235.                 DB      'Jun'           ;
  236.                 DB      'Jul'           ;
  237.                 DB      'Aug'           ;
  238.                 DB      'Sep'           ;
  239.                 DB      'Oct'           ;
  240.                 DB      'Nov'           ;
  241.                 DB      'Dec'           ;
  242. TD_TAB          LABEL   WORD            ; Pattern table for time/date
  243.                 DW      'DW'            ;
  244.                 DW      'MN'            ;
  245.                 DW      'MM'            ;
  246.                 DW      'DD'            ;
  247.                 DW      'CC'            ;
  248.                 DW      'YY'            ;
  249.                 DW      'hh'            ;
  250.                 DW      'mm'            ;
  251.                 DW      'ss'            ;
  252. L_TD            EQU     ($-TD_TAB)/2    ; Number entries
  253. TD_LOC          DW      DOW             ;
  254.                 DW      MON             ;
  255.                 DW      MONTH           ;
  256.                 DW      DAY             ;
  257.                 DW      CENTURY         ;
  258.                 DW      YEAR            ;
  259.                 DW      HOUR            ;
  260.                 DW      MINUTE          ;
  261.                 DW      SECOND          ;
  262. ;
  263. ; Key handling tables.
  264. ;
  265. KEY_TAB         LABEL   WORD            ; Keys requiring special handling
  266.                 DW      CR_CHR          ; Carriage return
  267.                 DW      LF_CHR          ; Ctrl Enter
  268.                 DW      TAB_CHR         ; Tab
  269.                 DW      ESC_CHR         ; Esc
  270.                 DW      BS_CHR          ; Backspace
  271.                 DW      15*256          ; Back tab
  272.                 DW      71*256          ; Home
  273.                 DW      72*256          ; Up arrow
  274.                 DW      73*256          ; PgUp
  275.                 DW      75*256          ; Left arrow
  276.                 DW      77*256          ; Right arrow
  277.                 DW      79*256          ; End
  278.                 DW      80*256          ; Down arrow
  279.                 DW      81*256          ; PgDn
  280.                 DW      82*256          ; Ins
  281.                 DW      83*256          ; Del
  282.                 DW      117*256         ; Ctrl End
  283.                 DW      119*256         ; Ctrl Home
  284.                 DW      59*256          ; F1
  285. L_KEYT          EQU     ($-KEY_TAB)/2   ; Number entries if not editing screen
  286.                 DW      60*256          ; F2
  287.                 DW      61*256          ; F3
  288.                 DW      62*256          ; F4
  289.                 DW      63*256          ; F5
  290.                 DW      64*256          ; F6
  291.                 DW      65*256          ; F7
  292.                 DW      66*256          ; F8
  293.                 DW      67*256          ; F9
  294.                 DW      68*256          ; F10
  295.                 DW      131*256         ; Alt =
  296. L_EDIT          EQU     ($-KEY_TAB)/2   ; Number of entries if editing screen
  297. KEY_VECT        LABEL   WORD            ; Vector for key processing routines
  298.                 DW      EDIT_PUT        ;
  299.                 DW      CR_SUB          ;
  300.                 DW      CENTER_SUB      ;
  301.                 DW      TAB_SUB         ;
  302.                 DW      ESC_SUB         ;
  303.                 DW      BS_SUB          ;
  304.                 DW      BTAB_SUB        ;
  305.                 DW      HOME_SUB        ;
  306.                 DW      UP_SUB          ;
  307.                 DW      PGUP_SUB        ;
  308.                 DW      LEFT_SUB        ;
  309.                 DW      RIGHT_SUB       ;
  310.                 DW      END_SUB         ;
  311.                 DW      DOWN_SUB        ;
  312.                 DW      PGDN_SUB        ;
  313.                 DW      INS_SUB         ;
  314.                 DW      DEL_SUB         ;
  315.                 DW      CEND_SUB        ;
  316.                 DW      CHOME_SUB       ;
  317.                 DW      HELP_SUB        ;
  318.                 DW      SETND_SUB       ;
  319.                 DW      FSHOW_SUB       ;
  320.                 DW      FDEL_SUB        ;
  321.                 DW      CNSTRT_SUB      ;
  322.                 DW      CNEND_SUB       ;
  323.                 DW      FSTRT_SUB       ;
  324.                 DW      FEND_SUB        ;
  325.                 DW      ATTR_SUB        ;
  326.                 DW      COLOR_SUB       ;
  327.                 DW      FORCE_SUB       ;
  328. ;
  329. ; Search and vector table for screen file conversion.
  330. ;
  331. SCR_CHR         LABEL   BYTE            ;
  332.                 DB      CR_CHR,LF_CHR,ESC_CHR ;
  333. L_DOPT          EQU     $-SCR_CHR       ; Length if display only
  334.                 DB      '\[]{}'         ;
  335. L_SCHR          EQU     $-SCR_CHR       ;
  336. SCR_VECT        LABEL   WORD            ;
  337.                 DW      SCR_PUT         ; If no match, just put character
  338.                 DW      SCR_CR          ;
  339.                 DW      SCR_LF          ;
  340.                 DW      SCR_ANSI        ;
  341.                 DW      SCR_FORCE       ;
  342.                 DW      SCR_LBRK        ;
  343.                 DW      SCR_RBRK        ;
  344.                 DW      SCR_LBRACE      ;
  345.                 DW      SCR_RBRACE      ;
  346. ;
  347. ; Search and vector table for pattern replacement.
  348. ;
  349. REPL_CHR        LABEL   BYTE            ;
  350.                 DB      '\?=|]'        ;
  351. L_RCHR          EQU     $-REPL_CHR      ;
  352. REPL_VECT       LABEL   WORD            ;
  353.                 DW      REPL_PUT        ; If no match, just put character
  354.                 DW      COPY_FORCE      ;
  355.                 DW      COPY_ONE        ;
  356.                 DW      COPY_LINE       ;
  357.                 DW      COPY_STOP       ;
  358.                 DW      COPY_REST       ;
  359. ;
  360. ; Search and vector table for template file processing.
  361. ;
  362. TMPL_CHR        LABEL   BYTE            ;
  363.                 DB      '\[]{}<>'       ;
  364. L_TCHR          EQU     $-TMPL_CHR      ;
  365. TMPL_VECT       LABEL   WORD            ;
  366.                 DW      TMPL_PUT        ; If no match, just put character
  367.                 DW      TMPL_FORCE      ;
  368.                 DW      TMPL_SENT       ;
  369.                 DW      TMPL_ERROR      ;
  370.                 DW      TMPL_CONST      ;
  371.                 DW      TMPL_ERROR      ;
  372.                 DW      TMPL_FILE       ;
  373.                 DW      TMPL_ERROR      ;
  374. ;
  375. ; Attribute tables for ANSI sequence.
  376. ;
  377. ATTR_MASK       LABEL   BYTE            ;
  378.                 DB      0               ; White on black
  379.                 DB      0FFH            ; Bold
  380.                 DB      0FFH            ;
  381.                 DB      0FFH            ;
  382.                 DB      0F8H            ; Underline
  383.                 DB      0FFH            ; Blink
  384.                 DB      0FFH            ;
  385.                 DB      077H            ; Reverse video
  386.                 DB      070H            ; Invisible
  387.                 DB      29-8 DUP(0FFH)  ; Unused
  388.                 DB      070H            ; Black foreground
  389.                 DB      070H            ; Red foreground
  390.                 DB      070H            ; Green foreground
  391.                 DB      070H            ; Yellow foreground
  392.                 DB      070H            ; Blue foreground
  393.                 DB      070H            ; Magenta foreground
  394.                 DB      070H            ; Cyan foreground
  395.                 DB      070H            ; White foreground
  396.                 DB      39-37 DUP(0FFH) ; Unused
  397.                 DB      0FH             ; Black background
  398.                 DB      0FH             ; Red background
  399.                 DB      0FH             ; Green background
  400.                 DB      0FH             ; Yellow background
  401.                 DB      0FH             ; Blue background
  402.                 DB      0FH             ; Magenta background
  403.                 DB      0FH             ; Cyan background
  404.                 DB      0FH             ; White background
  405. L_ATTR          EQU     $-ATTR_MASK     ; Number of attribute values
  406. ATTR_VAL        LABEL   BYTE            ;
  407.                 DB      7               ; White on black
  408.                 DB      8               ; Bold on
  409.                 DB      0               ;
  410.                 DB      0               ;
  411.                 DB      1               ; Underline
  412.                 DB      80H             ; Blink
  413.                 DB      0               ;
  414.                 DB      0               ; Reverse
  415.                 DB      0               ; Hidden
  416.                 DB      29-8 DUP(0)     ; Unused
  417.                 DB      0               ; Black foreground
  418.                 DB      4               ; Red foreground
  419.                 DB      2               ; Green foreground
  420.                 DB      6               ; Yellow foreground
  421.                 DB      1               ; Blue foreground
  422.                 DB      5               ; Magenta foreground
  423.                 DB      3               ; Cyan foreground
  424.                 DB      7               ; White foreground
  425.                 DB      39-37 DUP(0)    ; Unused
  426.                 DB      0               ; Black background
  427.                 DB      40H             ; Red background
  428.                 DB      20H             ; Green background
  429.                 DB      60H             ; Yellow background
  430.                 DB      10H             ; Blue background
  431.                 DB      50H             ; Magenta background
  432.                 DB      30H             ; Cyan background
  433.                 DB      70H             ; White background
  434. ;
  435. ; Status line.
  436. ;
  437. C10             DB      10,0            ; Constant 10
  438. C100            DB      100             ; Constant 100
  439. STAT_ATTR       EQU     1FH             ; White on blue
  440. STATUS_MSG      DB      'COL='          ;
  441. STAT_COL        DB      'xxx, ROW='     ;
  442. STAT_ROW        DB      'xxx, LN='      ;
  443. STAT_LIN        DB      'xxx'           ;
  444.                 DB      ' '             ;
  445. STAT_INS        DB      ' '             ;
  446.                 DB      ' '             ;
  447. STAT_Q          DB      ' '             ;
  448.                 DB      71-($-STATUS_MSG) DUP(' ') ;
  449. Q_LNG           EQU     $-STAT_Q        ; Max length of messages
  450.                 DB      'F1 = Help'     ;
  451.                 DB      80 DUP(' ')     ; Status lines up to 160 characters
  452. ;
  453. ; Menu for selecting colors and attributes.
  454. ;
  455. COLOR_MNU       LABEL   WORD            ;
  456.                 DBA %(SCR_ATTR OR 8),<                 COLORS                 >
  457.                 DBA     SCR_ATTR,<                                        > ;
  458.                 DBA     SCR_ATTR,<Select text color(0-15) background(0-7) > ;
  459.                 DBA     SCR_ATTR,<       and blink(Y,N)                   > ;
  460.                 DBA     SCR_ATTR,<Press Enter when done                   > ;
  461.                 DBA     SCR_ATTR,<                                        > ;
  462.                 DBA          70H,< 0 = Black          > ;
  463.                 DBA            8,< 8 = Dark grey      > ;
  464.                 DBA            1,< 1 = Blue           > ;
  465.                 DBA            9,< 9 = Bright blue    > ;
  466.                 DBA            2,< 2 = Green          > ;
  467.                 DBA           10,<10 = Bright green   > ;
  468.                 DBA            3,< 3 = Cyan           > ;
  469.                 DBA           11,<11 = Bright cyan    > ;
  470.                 DBA            4,< 4 = Red            > ;
  471.                 DBA           12,<12 = Bright Red     > ;
  472.                 DBA            5,< 5 = Magenta        > ;
  473.                 DBA           13,<13 = Bright Magenta > ;
  474.                 DBA            6,< 6 = Brown          > ;
  475.                 DBA           14,<14 = Yellow         > ;
  476.                 DBA            7,< 7 = White          > ;
  477.                 DBA           15,<15 = Bright white   > ;
  478. L_CTAB          EQU     ($-COLOR_MNU)/80        ; Number of lines in menu
  479. ;
  480. ; HELP display
  481. ;
  482. HELP_MNU        LABEL   WORD                    ;
  483.                 DBA %(SCR_ATTR OR 8),<            KEY DEFINITIONS             >
  484.                 DBA     SCR_ATTR,<                                        > ;
  485.                 DBA     SCR_ATTR,<Press Enter when done                   > ;
  486.                 DBA     SCR_ATTR,<                                        > ;
  487.                 DBA     SCR_ATTR,<Esc = Quit          > ;
  488.                 DBA     SCR_ATTR,<Ctrl Enter = Done   > ;
  489.                 DBA     SCR_ATTR,<F1 = Key definition > ;
  490.                 DBA     SCR_ATTR,<Enter = Field done  > ;
  491.                 DBA     SCR_ATTR,<Tab = Next field    > ;
  492.                 DBA     SCR_ATTR,<ShiftTab = Tab back > ;
  493.                 DBA     SCR_ATTR,<Home = Field start  > ;
  494.                 DBA     SCR_ATTR,<End = Field end     > ;
  495.                 DBA     SCR_ATTR,<Ctrl Home = Top     > ;
  496.                 DBA     SCR_ATTR,<Ctrl End = Bottom   > ;
  497.                 DBA     SCR_ATTR,<Ins = Insert mode   > ;
  498.                 DBA     SCR_ATTR,<Del = Delete char   > ;
  499. L_HELP          EQU     ($-HELP_MNU)/80 ; Number of lines if not editing
  500.                 DBA     SCR_ATTR,<Alt= = Insert key   > ;
  501.                 DBA     SCR_ATTR,<F2 = Set end screen > ;
  502.                 DBA     SCR_ATTR,<F3 = Display Fields > ;
  503.                 DBA     SCR_ATTR,<F4 = Delete Field   > ;
  504.                 DBA     SCR_ATTR,<F5 = Start Constant > ;
  505.                 DBA     SCR_ATTR,<F6 = End Constant   > ;
  506.                 DBA     SCR_ATTR,<F7 = Start Field    > ;
  507.                 DBA     SCR_ATTR,<F8 = End Field      > ;
  508.                 DBA     SCR_ATTR,<F9 = Select color   > ;
  509.                 DBA     SCR_ATTR,<F10 = Color char    > ;
  510. L_HMNU          EQU     ($-HELP_MNU)/80 ; Number of lines in menu
  511. ;
  512. ; Code area.
  513. ;
  514. BEGIN:                                  ;
  515. ;
  516. ; Copy screen file to editing buffer.
  517. ; Editing buffer is layed out in screen format.
  518. ;
  519.                 MOV     DI,OFFSET EDIT_LOC ;
  520.                 MOV     AH,SCR_ATTR     ; Default attribute
  521.                 MOV     BX,SCREENFILE   ;
  522.                 CMP     DOPT,L_DOPT     ; If /D option, allow STDIN
  523.                 JE      SCR_LINE        ;
  524.                 OR      BX,BX           ; Any screen file?
  525.                 JZ      SCR_DONE        ; No, Just use an empty file
  526. ;
  527. ; Get next character and check for special cases.
  528. ; For CR, treat as end of line and skip an immediately following LF.
  529. ; For LF, treat as end of line.
  530. ; For ESC, process ANSI SGR sequence.
  531. ; For \, use next character even if it is a special character.
  532. ; For [], build input field
  533. ; For {}, build constant field
  534. ; For anything else, just use the character.
  535. ;
  536. SCR_LINE:                               ;
  537.                 MOV     DX,WORD PTR SCR_COL ; Number of columns on screen
  538. SCR_GET:                                ;
  539.                 CALL    GET_CHR         ;
  540.                 JZ      SCR_END         ; If no more characters
  541. SCR_GOT:                                ;
  542.                 MOV     CX,DOPT         ; Length for display type
  543.                 MOV     SI,OFFSET SCR_CHR ;
  544.                 CALL    TBL_SRCH        ; Find character type
  545.                 JMP     SCR_VECT[SI]    ; Branch on character type
  546. ;
  547. ; Just put the character and the current attribute in the display.
  548. ;
  549. SCR_PUT:                                ;
  550.                 CMP     DI,EDIT_LAST    ; Buffer full?
  551.                 JA      SCR_ERROR       ; File too big
  552.                 STOSW                   ; Store character
  553.                 DEC     DX              ; Starting a new line on screen?
  554.                 JNS     SCR_GET         ; No
  555.                 ADD     DX,WORD PTR SCR_COL ; Chars remaining in new line
  556.                 JMP     SCR_GET         ;
  557. ;
  558. ; Got a line feed (LF) which always means end of record.
  559. ;
  560. SCR_LF:                                 ;
  561.                 CALL    SCR_PAD         ; Close out line
  562.                 JMP     SCR_LINE        ; and start another
  563. ;
  564. ; Got a CR which means end of record.  Must check for a line feed following
  565. ; and skip it if found.
  566. ;
  567. SCR_CR:                                 ;
  568.                 CALL    SCR_PAD         ; Close out line
  569.                 MOV     DL,SCR_COL      ; Start new line
  570.                 CALL    GET_CHR         ; Get next character
  571.                 JZ      SCR_DONE        ; No more characters
  572.                 CMP     AL,LF_CHR       ; Is it a LF?
  573.                 JNE     SCR_GOT         ; No, go process it
  574.                 JMP     SCR_GET         ; Yes, go get next character
  575. ;
  576. ; End of file
  577. ;
  578. SCR_END:                                ;
  579.                 CMP     DL,SCR_COL      ; Started a line?
  580.                 JAE     SCR_DONE        ; No
  581.                 CALL    SCR_PAD         ; Fill out line to end
  582. SCR_DONE:                               ;
  583.                 JMP     EDIT_RDY        ;
  584. ;
  585. ; Insert spaces into screen line for remainder of line.
  586. ; DX = space count
  587. ;
  588. SCR_PAD:                                ;
  589.                 MOV     CX,DX           ; Remaining character count
  590.                 MOV     AL,' '          ; Space character.
  591.         REP     STOSW                   ;
  592.                 MOV     DX,CX           ; No characters remaining
  593.                 CMP     DI,EDIT_LAST    ; Overflow?
  594.                 JA      SCR_ERROR       ; Yes
  595.                 RET                     ;
  596. ;
  597. ; Expanded file is too big.
  598. ;
  599. SCR_ERROR:                              ;
  600.                 MOV     DX,OFFSET BIG_MSG ;
  601.                 MOV     CX,L_BIG        ;
  602.                 JMP     ERROR_DSP       ;
  603. ;
  604. ; Found a \.  Put the next character no matter what it is.
  605. ;
  606. SCR_FORCE:                              ;
  607.                 CALL    GET_CHR         ;
  608.                 JZ      SCR_END         ;
  609.                 JMP     SCR_PUT         ;
  610. ;
  611. ; Found a [.  Start input field.
  612. ;
  613. SCR_LBRK:                               ;
  614.                 MOV     SI,EDIT_NUM     ; Loc of next input area control
  615.                 CMP     SI,EDIT_FLD*4   ; Already too many?
  616.                 JAE     INP_ERROR       ; No
  617.                 CMP     EDIT_AREA[SI],0 ; Already started an input area?
  618.                 JNZ     INP_ERROR       ;
  619.                 MOV     EDIT_AREA[SI],DI ; Save start of input area
  620.                 JMP     SCR_GET         ; Go get next character
  621. ;
  622. ; Found a ].  End input field.
  623. ;
  624. SCR_RBRK:                               ;
  625.                 MOV     SI,EDIT_NUM     ;
  626.                 CMP     SI,EDIT_FLD*4   ; Already too many?
  627.                 JAE     INP_ERROR       ; No
  628.                 CMP     EDIT_AREA[SI],0 ; Start of area found?
  629.                 JZ      INP_ERROR       ; No, error
  630.                 MOV     EDIT_AREA[SI+2],DI ; Save end of area
  631.                 ADD     EDIT_NUM,4      ; Move to next area
  632.                 JMP     SCR_GET         ;
  633. INP_ERROR:                              ; Unbalanced or too many []'s
  634.                 MOV     DX,OFFSET INP_MSG ;
  635.                 MOV     CX,L_INP        ;
  636.                 JMP     ERROR_DSP       ; Go display error message
  637. ;
  638. ; Found an ANSI sequence.  Form new attribute value.
  639. ;
  640. SCR_ANSI:                               ;
  641.                 CALL    GET_CHR         ; We have the Esc, look for [
  642.                 JZ      ANSI_ERROR      ;
  643.                 CMP     AL,'['          ; ESC [ ?
  644.                 JNE     ANSI_ERROR      ; No
  645.                 PUSH    DX              ;
  646.                 MOV     CL,4            ;
  647. SCR_ALP:                                ;
  648.                 CALL    DTB             ; Get binary value
  649.                 CMP     DX,L_ATTR       ; Legal attribute value?
  650.                 JAE     ANSI_ERROR      ; No, error
  651.                 MOV     SI,DX           ;
  652.                 AND     AH,ATTR_MASK[SI] ; Mask attribute to be changed out
  653.                 OR      AH,ATTR_VAL[SI] ; Put in new value
  654.                 CMP     DL,7            ; Reverse video?
  655.                 JNE     SCR_INV         ; No
  656.                 ROL     AH,CL           ;
  657. SCR_INV:                                ;
  658.                 CMP     DL,8            ; Canceled(invisible)?
  659.                 JNE     SCR_SEP         ; No
  660.                 MOV     DH,AH           ; Make foreground=background
  661.                 SHR     DH,CL           ;
  662.                 OR      AH,DH           ;
  663. SCR_SEP:                                ;
  664.                 CMP     AL,';'          ; Sub-field separator?
  665.                 JE      SCR_ALP         ; Yes, continue
  666.                 CMP     AL,'m'          ; End of SGR sequence?
  667.                 JNE     ANSI_ERROR      ; No
  668.                 POP     DX              ;
  669.                 JMP     SCR_GET         ; Yes
  670. ANSI_ERROR:                             ; Not a supported Esc sequence
  671.                 MOV     DX,OFFSET ANSI_MSG ;
  672.                 MOV     CX,L_ANSI       ;
  673.                 JMP     ERROR_DSP       ;
  674. ;
  675. ; { indicating beginning of constant area.
  676. ;
  677. SCR_LBRACE:                             ;
  678.                 MOV     SI,CONST_NUM    ; Loc of next constant area control
  679.                 CMP     SI,EDIT_FLD*4   ; Already too many?
  680.                 JAE     CONST_ERROR     ; No
  681.                 CMP     CONST_AREA[SI],0 ; Already started a constant area?
  682.                 JNZ     CONST_ERROR     ;
  683.                 MOV     CONST_AREA[SI],DI ; Save start of constant area
  684.                 JMP     SCR_GET         ; Go get next character
  685. ;
  686. ; Found a }.  End constant area.
  687. ;
  688. SCR_RBRACE:                             ;
  689.                 MOV     SI,CONST_NUM    ;
  690.                 CMP     SI,EDIT_FLD*4   ; Already too many?
  691.                 JAE     CONST_ERROR     ; No
  692.                 CMP     CONST_AREA[SI],0 ; Start of area found?
  693.                 JZ      CONST_ERROR     ; No, error
  694.                 MOV     CONST_AREA[SI+2],DI ; Save end of area
  695.                 ADD     CONST_NUM,4     ; Move to next area
  696.                 JMP     SCR_GET         ;
  697. CONST_ERROR:                            ;
  698.                 MOV     CX,L_CONST      ;
  699.                 MOV     DX,OFFSET CONST_MSG ;
  700.                 JMP     ERROR_DSP       ;
  701. ;
  702. ; Check for unbalanced []'s and {}'s.
  703. ;
  704. EDIT_RDY:                               ;
  705.                 MOV     SI,EDIT_NUM     ;
  706.                 CMP     SI,EDIT_FLD*4   ; Area full?
  707.                 JAE     EDIT_BRACE      ; Yes, everything is OK
  708.                 CMP     EDIT_AREA[SI],0 ; Started next field?
  709.                 JZ      EDIT_BRACE      ; No
  710.                 JMP     INP_ERROR       ; Yes, error
  711. EDIT_BRACE:                             ;
  712.                 MOV     SI,CONST_NUM    ;
  713.                 CMP     SI,EDIT_FLD*4   ; Full?
  714.                 JAE     EDIT_OK         ;
  715.                 CMP     CONST_AREA[SI],0 ; Started next constant.
  716.                 JNZ     CONST_ERROR     ;
  717. EDIT_OK:                                ;
  718.                 DEC     DI              ; Update end of file
  719.                 DEC     DI              ;
  720. ;
  721. ; If the /E option is set, copy all existing input field definitions to the
  722. ; New field area and set the entire display to a single input field.
  723. ;
  724.                 CMP     EOPT,L_EDIT     ; Editing a screen file?
  725.                 JNE     EDIT_NORM       ; No normal file editing
  726.                 MOV     CX,EDIT_NUM     ; Length to copy
  727.                 MOV     SI,OFFSET EDIT_AREA-1 ; Copy input definition to
  728.                 ADD     SI,CX           ;
  729.                 MOV     DI,OFFSET DEF_AREA-1 ; new input definitions
  730.                 ADD     DI,CX           ;
  731.                 MOV     DEF_NUM,CX      ;
  732.                 STD                     ; Overlapping fields
  733.         REP     MOVSB                   ;
  734.                 CLD                     ;
  735.                 MOV     EDIT_NUM,4      ; Define a single input field
  736.                 MOV     EDIT_AREA,OFFSET EDIT_LOC ; covering the entire file
  737.                 MOV     DI,EDIT_LAST    ;
  738.                 MOV     EDIT_AREA+2,DI  ;
  739.                 MOV     SCRN_END,DI     ; Default end of screen definition
  740. EDIT_NORM:                              ;
  741.                 MOV     EDIT_LAST,DI    ;
  742.                 CMP     DI,OFFSET EDIT_LOC-2 ; Empty file?
  743.                 JA      EDIT_NMT        ; No
  744.                 JMP     CENTER_SUB      ; Yes, just exit
  745. EDIT_NMT:                               ;
  746. ;
  747. ; Display first screen of file.
  748. ;
  749.                 CALL    CHOME_SUB       ; Display first page
  750. ;
  751. ; Now get a key and process editing commands.
  752. ;
  753. EDIT_FILE:                              ;
  754.                 XOR     AH,AH           ;
  755.                 INT     KYBD$           ; Read next character
  756.                 OR      AL,AL           ; Extended key?
  757.                 JZ      EDIT_XTND       ; Yes
  758.                 XOR     AH,AH           ; Clear scan code
  759. EDIT_XTND:                              ;
  760. ;
  761. ; Determine type of key and switch to proper routine to handle that key type.
  762. ;
  763.                 PUSH    SI              ;
  764.                 MOV     CX,EOPT         ;
  765.                 MOV     SI,OFFSET KEY_TAB ;
  766.                 CALL    WTBL_SRCH       ; Find matching entry
  767.                 MOV     BX,SI           ;
  768.                 POP     SI              ;
  769.                 CALL    KEY_VECT[BX]    ; Go to key routine
  770.                 JMP     EDIT_FILE       ;
  771. ;
  772. ; Put character in file and display.  All normal keys.
  773. ;
  774. EDIT_PUT:                               ;
  775.                 CMP     AL,0            ; Don't put NULs
  776.                 JZ      EDIT_STATUS     ;
  777. EDIT_FORCE:                             ;
  778.                 CALL    FIND_AREA       ; Are we in an input field?
  779.                 JC      EDIT_STATUS     ; No, do nothing
  780.                 CMP     STAT_INS,' '    ; Are we inserting?
  781.                 JE      EDIT_NINS       ; No, just store the character
  782. ;
  783. ; Insert a character in this input area.
  784. ;
  785.                 PUSH    DI              ;
  786.                 PUSH    SI              ;
  787.                 MOV     DI,EDIT_AREA[BX+2] ; Amount to move
  788.                 DEC     DI              ;
  789.                 DEC     DI              ;
  790.                 CMP     SI,DI           ; At end of area?
  791.                 JAE     EDIT_NMV        ; Yes, don't move anything
  792.                 MOV     CX,DI           ;
  793.                 SUB     CX,SI           ;
  794.                 LEA     SI,[DI-2]       ;
  795.                 SHR     CX,1            ;
  796.                 STD                     ;
  797.         REP     MOVSW                   ; Copy characters
  798.                 CLD                     ;
  799. EDIT_NMV:                               ;
  800.                 POP     SI              ;
  801.                 POP     DI              ;
  802.                 MOV     [SI],AL         ;
  803.                 CALL    DISP_SCREEN     ; Display the modified field
  804.                 JMP     SHORT RIGHT_SUB ;
  805. ;
  806. ; Put character in file buffer and display.
  807. ;
  808. EDIT_NINS:                              ;
  809.                 MOV     [SI],AL         ; Put key in file
  810.                 MOV     AH,[SI+1]       ;
  811.                 CALL    WRITE_SCREEN    ;
  812.                 DEC     DI              ; Don't move cursor here
  813.                 DEC     DI              ;
  814. ;
  815. ; Increment cursor position.
  816. ;
  817. RIGHT_SUB:                              ; Right arrow
  818.                 MOV     AX,1            ;
  819. ;
  820. ; General logic to move the cursor.
  821. ; If it would move outside the file, it is moved the maximum amount.
  822. ; If it moves outside the current screen, the screen is moved.
  823. ; This logic is only good for moves of <8000H bytes.
  824. ; Entered with AX = Amount to move cursor, positive or negative.
  825. ;
  826. MOVE_CRS:                               ;
  827.                 CWD                     ; Extend sign
  828.                 SHL     AX,1            ; Make into word offset
  829.                 ADD     AX,SI           ; Adjust file pointer
  830.                 ADC     DX,0            ;
  831.                 JS      CHOME_SUB       ; Negative is before start
  832.                 JNZ     CEND_SUB        ; Too large, so after end
  833.                 CMP     AX,OFFSET EDIT_LOC ; Before start of file?
  834.                 JB      CHOME_SUB       ; Yes
  835.                 CMP     AX,EDIT_LAST    ; Beyond end?
  836.                 JA      CEND_SUB        ; Yes
  837. ;
  838. ; Move to a specific display position.
  839. ; Because we could be moving 16384 (8000H) bytes or more, we must handle the
  840. ; calculations with double precision arithmetic.
  841. ; Enter with AX = New display position.
  842. ;
  843. MOVE_TO:                                ;
  844.                 XCHG    SI,AX           ; New file position
  845.                 SUB     AX,SI           ; Distance from old to new
  846.                 SBB     DX,DX           ; Sign extend distance to high order
  847.                 SUB     DI,AX           ; New cursor index
  848.                 ADC     DX,0            ; Slight cheat knowing sign of DI
  849.                 JS      MOVE_FWD        ; DI>64K, move screen forward
  850.                 JNZ     MOVE_BACK       ; DI<0, move screen backward
  851.                 CMP     DI,DISP_SIZE    ; Off end of screen?
  852.                 JAE     MOVE_FWD        ; Must move screen forward
  853.                 CALL    FIND_AREA       ; Get next input field
  854.                 JNC     EDIT_STATUS     ; Already in one
  855.                 MOV     AX,EDIT_AREA[BX] ; Start of next area
  856.                 SUB     AX,SI           ; Offset to start of next area
  857.                 JB      EDIT_STATUS     ; Don't move back to area
  858.                 MOV     CX,AX           ;
  859.                 ADD     CX,DI           ; Cursor index of next area
  860.                 SHR     AX,1            ;
  861.                 CMP     CX,DISP_SIZE    ; Still on screen?
  862.                 JB      MOVE_CRS        ; Yes, move cursor to input area
  863. ;
  864. ; Update status line with cursor position and move video cursor.
  865. ;
  866. EDIT_STATUS:                            ;
  867.                 CALL    STAT_CLR        ; Clear any message in status line
  868.                 CALL    STATUS          ; Display status line
  869.                 XOR     BH,BH           ; Video page 0
  870.                 MOV     AX,DI           ;
  871.                 SHR     AX,1            ;
  872.                 DIV     SCR_COL         ; Compute new cursor position
  873.                 XCHG    AL,AH           ;
  874.                 MOV     DX,AX           ;
  875.                 MOV     AH,CRS$         ; Update cursor position
  876.                 INT     VIDEO$          ;
  877.                 RET                     ;
  878. ;
  879. ; Ctrl Home = Go to top of display.
  880. ;
  881. CHOME_SUB:                              ; Ctrl Home
  882.                 MOV     SI,OFFSET EDIT_LOC ; Move back to start
  883. ;
  884. ; Move display back until new position is in first line on screen.
  885. ;
  886. MOVE_BACK:                              ;
  887.                 XOR     DI,DI           ; Cursor line is top of screen
  888.                 JMP     SHORT MOVE_SCRN ;
  889. ;
  890. ; Move display forward until new position is in last line on screen.
  891. ;
  892. MOVE_FWD:                               ;
  893.                 MOV     DI,DISP_SIZE    ;
  894.                 SUB     DI,WORD PTR SCR_COL ; Cursor is in last line
  895.                 SUB     DI,WORD PTR SCR_COL ;
  896. MOVE_SCRN:                              ;
  897.                 LEA     AX,[SI-(OFFSET EDIT_LOC - OFFSET MENU_PSP)] ;
  898.                 SHR     AX,1            ;
  899.                 CWD                     ; May be more than 256 lines
  900.                 DIV     WORD PTR SCR_COL ; Compute new column position
  901.                 SHL     DX,1            ; Remainder is column
  902.                 ADD     DI,DX           ; New cursor position
  903.                 CALL    DISP_SCREEN     ; Redisplay screen
  904.                 XOR     AX,AX           ; Find field position
  905.                 JMP     MOVE_CRS        ;
  906. ;
  907. ; Ctrl End = Go to end of display.
  908. ;
  909. CEND_SUB:                               ; Ctrl End
  910.                 MOV     AX,EDIT_LAST    ; Move to end of display area
  911.                 JMP     MOVE_TO         ;
  912. ;
  913. ; CR = Go to next line in a multi-line field, or to next field, or exit
  914. ; if in last line of last field.
  915. ;
  916. CR_SUB:                                 ; CR
  917.                 CALL    FIND_AREA       ; Find which area we are in
  918.                 JC      CR_TAB          ; Not in an area
  919.                 MOV     AX,DI           ;
  920.                 SHR     AX,1            ;
  921.                 DIV     SCR_COL         ; Offset to start of next line
  922.                 MOV     AL,SCR_COL      ;
  923.                 SUB     AL,AH           ;
  924.                 XOR     AH,AH           ;
  925.                 SHL     AX,1            ;
  926.                 ADD     AX,SI           ;
  927.                 CMP     AX,EDIT_AREA[BX+2] ; Beyond end of area?
  928.                 JB      GO_MTO          ; No, just move to next line
  929.                 ADD     BX,4            ;
  930. CR_TAB:                                 ; Go to next area or quit
  931.                 CMP     BX,EDIT_NUM     ; In last field?
  932.                 JAE     GO_CENTER       ; Yes
  933.                 CMP     SI,EDIT_AREA[BX] ; After last field?
  934.                 JB      TAB_SUB         ; No, move to next field
  935. GO_CENTER:                              ;
  936.                 JMP     CENTER_SUB      ; Yes, end of entry
  937. ;
  938. ; Down arrow = Move down one line.
  939. ;
  940. DOWN_SUB:                               ; Down arrow
  941.                 MOV     AX,WORD PTR SCR_COL ; Move one line
  942.                 JMP     MOVE_CRS        ;
  943. ;
  944. ; Up arrow = Move up one line.
  945. ;
  946. UP_SUB:                                 ; Up arrow
  947.                 MOV     AX,WORD PTR SCR_COL ; Move up one line
  948.                 NEG     AX              ;
  949.                 JMP     MOVE_CRS        ;
  950. ;
  951. ; PgUp = Move up one page.
  952. ;
  953. PGUP_SUB:                               ; PgUp
  954.                 MOV     AX,DISP_SIZE    ;
  955.                 SHR     AX,1            ;
  956.                 NEG     AX              ; Move back one page
  957.                 JMP     MOVE_CRS        ; Move to next input area if any
  958. ;
  959. ; PgDn = Move down one page.
  960. ;
  961. PGDN_SUB:                               ; PgDn
  962.                 MOV     AX,DISP_SIZE    ; Move ahead one screen
  963.                 SHR     AX,1            ;
  964.                 JMP     MOVE_CRS        ;
  965. ;
  966. ; Tab = Move to start of next field.
  967. ;
  968. TAB_SUB:                                ; TAB
  969.                 CMP     EDIT_NUM,0      ; Any input areas?
  970.                 JZ      GO_EST          ; No, nothing to do
  971.                 CALL    FIND_AREA       ; Find current area
  972.                 JC      TAB_OK          ; Point to next area
  973.                 ADD     BX,4            ; Move to next area
  974.                 CMP     BX,EDIT_NUM     ; Wrap around?
  975.                 JB      TAB_OK          ;
  976.                 XOR     BX,BX           ;
  977. TAB_OK:                                 ;
  978.                 MOV     AX,EDIT_AREA[BX] ; Move to start of next area
  979. GO_MTO:                                 ;
  980.                 JMP     MOVE_TO         ;
  981. ;
  982. ; Home and Back tab = Move to start of this field.  If at start, move to
  983. ; start of previous field.
  984. ;
  985. HOME_SUB:                               ; Home
  986. BTAB_SUB:                               ; Back tab
  987.                 CALL    FIND_AREA       ; Find current area
  988.                 JC      BTAB_AREA       ; Not in an area, just use previous
  989.                 MOV     AX,EDIT_AREA[BX] ;
  990.                 CMP     AX,SI           ; Already at start of area?
  991.                 JNE     GO_MTO          ; No, move to start of area
  992. BTAB_AREA:                              ;
  993.                 CMP     EDIT_NUM,0      ; Any input areas?
  994.                 JZ      GO_EST          ; No
  995.                 OR      BX,BX           ; First area?
  996.                 JNZ     BACK_AREA       ; No
  997.                 MOV     BX,EDIT_NUM     ; Yes, move to last area
  998. BACK_AREA:                              ;
  999.                 MOV     AX,EDIT_AREA[BX-4] ; Start of previous area
  1000.                 JMP     MOVE_TO         ;
  1001. GO_EST:                                 ;
  1002.                 JMP     EDIT_STATUS     ;
  1003. ;
  1004. ; Left arrow = Move cursor left one space.
  1005. ;
  1006. LEFT_SUB:                               ; Left arrow
  1007.                 MOV     AX,-1           ; Back one space
  1008.                 JMP     MOVE_CRS        ;
  1009. ;
  1010. ; End = Move to end of this field.  Moves to first space after last non-space.
  1011. ;
  1012. END_SUB:                                ; End
  1013.                 CALL    FIND_AREA       ; Find area
  1014.                 CMP     BX,EDIT_NUM     ; Any areas?
  1015.                 JAE     GO_EST          ; No, nothing to do
  1016.                 CALL    END_FIND        ; Find end of next area
  1017.                 CMP     AX,SI           ; Would we move?
  1018.                 JNE     GO_MTO          ; Yes, so move
  1019.                 CALL    TAB_SUB         ; Move to end of next area
  1020.                 CALL    FIND_AREA       ;
  1021.                 CALL    END_FIND        ;
  1022.                 JMP     MOVE_TO         ;
  1023. ;
  1024. ; Find end of area.
  1025. ;
  1026. END_FIND:                               ;
  1027.                 PUSH    DI              ;
  1028.                 MOV     DX,EDIT_AREA[BX] ; Start of area
  1029.                 MOV     DI,EDIT_AREA[BX+2] ; End of area
  1030.                 MOV     AH,[DI-1]       ; Attribute for first position
  1031.                 CALL    TRIM            ; Find last non-blank + 2
  1032.                 CMP     DI,EDIT_AREA[BX+2] ; Non-blank in last position
  1033.                 JB      EF_LAST         ; No
  1034.                 DEC     DI              ; Go to last position then
  1035.                 DEC     DI              ;
  1036. EF_LAST:                                ;
  1037.                 MOV     AX,DI           ; Position to move to
  1038.                 POP     DI              ;
  1039.                 RET                     ;
  1040. ;
  1041. ; Ins = Toggle insert mode.
  1042. ;
  1043. INS_SUB:                                ;
  1044.                 XOR     STAT_INS,' ' XOR '^' ; Toggle insert mode
  1045.                 JMP     EDIT_STATUS     ; Go display updated status
  1046. ;
  1047. ; Backspace = Move back one space and delete the character there.
  1048. ; If at first character of the field, do nothing.
  1049. ;
  1050. BS_SUB:                                 ; Backspace
  1051.                 CALL    FIND_AREA       ; Find current input area
  1052.                 JC      LEFT_SUB        ; Not in area, just move left
  1053.                 CMP     SI,EDIT_AREA[BX] ; Are we at start?
  1054.                 JNE     BS_LFT          ; No, move left
  1055.                 JMP     EDIT_STATUS     ; Nothing to do
  1056. BS_LFT:                                 ;
  1057.                 CALL    LEFT_SUB        ;
  1058. ;
  1059. ; Del = Delete the character under the cursor.
  1060. ;
  1061. DEL_SUB:                                ;
  1062.                 CALL    FIND_AREA       ; Find the area we are in
  1063.                 JC      GO_EST          ; Not in an area
  1064.                 MOV     CX,EDIT_AREA[BX+2] ;
  1065.                 DEC     CX              ; Last character of field
  1066.                 DEC     CX              ;
  1067.                 PUSH    CX              ; Save last position
  1068.                 SUB     CX,SI           ;
  1069.                 PUSH    DI              ;
  1070.                 PUSH    SI              ;
  1071.                 MOV     DI,SI           ;
  1072.                 INC     SI              ;
  1073.                 INC     SI              ;
  1074.         REP     MOVSB                   ; Copy characters
  1075.                 POP     SI              ;
  1076.                 POP     DI              ;
  1077.                 POP     BX              ;
  1078.                 MOV     BYTE PTR [BX],' ' ; Put a blank in the last spot
  1079.                 CALL    DISP_SCREEN     ; Display the field
  1080.                 RET                     ;
  1081. ;
  1082. ; F1 = Help.  Display key definitions.
  1083. ;
  1084. HELP_SUB:                               ;
  1085.                 MOV     AX,OFFSET HELP_MNU ;
  1086.                 MOV     CX,L_HELP       ; Length if not editing
  1087.                 CMP     EOPT,L_EDIT     ; Editing a screen file?
  1088.                 JNE     HELP_NRM        ; No
  1089.                 MOV     CX,L_HMNU       ;
  1090. HELP_NRM:                               ;
  1091.                 CALL    DISP_MNU        ; Display the menu
  1092. HELP_WT:                                ;
  1093.                 XOR     AH,AH           ;
  1094.                 INT     KYBD$           ;
  1095.                 CMP     AL,ESC_CHR      ;
  1096.                 JE      HELP_QUIT       ;
  1097.                 CMP     AL,CR_CHR       ;
  1098.                 JNE     HELP_WT         ; Wait for a CR
  1099. HELP_QUIT:                              ;
  1100.                 CALL    DISP_SCREEN     ; Refresh the screen
  1101.                 JMP     EDIT_STATUS     ;
  1102. ;
  1103. ; F2 = Send end of screen definition location.
  1104. ;
  1105. SETND_SUB:                              ;
  1106.                 MOV     SCRN_END,SI     ; Set new end of definition loc
  1107.                 JMP     EDIT_STATUS     ;
  1108. ;
  1109. ; F3 = Toggle field and constant display.
  1110. ;
  1111. FSHOW_SUB:                              ;
  1112.                 XOR     SHOW,1          ; Toggle show flag
  1113.                 CALL    DISP_SCREEN     ; Redisplay this screen
  1114.                 RET                     ;
  1115. ;
  1116. ; F4 = Erase field or constant definition at this location.
  1117. ;
  1118. FDEL_SUB:                               ; Erase definition
  1119.                 XOR     BX,BX           ; Loop through all definitions
  1120. FDEL_LP:                                ;
  1121.                 CMP     BX,DEF_NUM      ;
  1122.                 JAE     NO_FDEF         ;
  1123.                 CMP     SI,DEF_AREA[BX] ; Start of this field?
  1124.                 JNE     NO_FDEF         ; No
  1125.                 MOV     AX,OFFSET DEF_AREA ;
  1126.                 CALL    FD_RMV          ; Remove entry
  1127.                 SUB     DEF_NUM,4       ; Reduce count of entries
  1128.                 JMP     FDEL_LP         ; Check next entry
  1129. NO_FDEF:                                ;
  1130.                 CMP     BX,CONST_NUM    ;
  1131.                 JAE     NO_FCON         ;
  1132.                 CMP     SI,CONST_AREA[BX] ; Start of this constant?
  1133.                 JNE     NO_FCON         ; No
  1134.                 MOV     AX,OFFSET CONST_AREA ;
  1135.                 CALL    FD_RMV          ; Remove entry
  1136.                 SUB     CONST_NUM,4     ; Reduce count
  1137.                 JMP     NO_FDEF         ; Check next entry
  1138. NO_FCON:                                ;
  1139.                 ADD     BX,4            ;
  1140.                 CMP     BX,EDIT_FLD*4   ; More fields to check?
  1141.                 JB      FDEL_LP         ; Yes
  1142.                 CALL    DISP_SCREEN     ; Update display
  1143.                 RET                     ;
  1144. FD_RMV:                                 ;
  1145.                 PUSH    DI              ; Remove this entry
  1146.                 PUSH    SI              ;
  1147.                 MOV     CX,EDIT_FLD*4-4 ;
  1148.                 SUB     CX,BX           ; Length to move
  1149.                 MOV     DI,BX           ;
  1150.                 ADD     DI,AX           ;
  1151.                 LEA     SI,[DI+4]       ;
  1152.         REP     MOVSB                   ; Copy entries
  1153.                 XOR     AX,AX           ;
  1154.                 STOSW                   ;
  1155.                 STOSW                   ; Clear last entry
  1156.                 POP     SI              ;
  1157.                 POP     DI              ;
  1158.                 RET                     ;
  1159. ;
  1160. ; F5 = Start constant area.
  1161. ;
  1162. CNSTRT_SUB:                             ; Define new constant area
  1163.                 MOV     BX,CONST_NUM    ; Pointer to next field definition
  1164.                 CMP     BX,EDIT_FLD*4   ; Area full?
  1165.                 JAE     DEF_ERROR       ; Yes
  1166.                 CMP     CONST_AREA[BX],0 ; Already started the area?
  1167.                 JNZ     DEF_NEST        ; Yes, cannot nest
  1168.                 MOV     CONST_AREA[BX],SI ; Save start of area
  1169.                 CALL    DISP_SCREEN     ;
  1170.                 RET                     ;
  1171. ;
  1172. ; F6 = End of constant area.
  1173. ;
  1174. CNEND_SUB:                              ; End constant area
  1175.                 MOV     BX,CONST_NUM     ;
  1176.                 CMP     BX,EDIT_FLD*4   ; Full?
  1177.                 JAE     DEF_ERROR       ;
  1178.                 CMP     CONST_AREA[BX],0 ; Started area?
  1179.                 JZ      DEF_UNBAL       ; No
  1180.                 LEA     AX,[SI+2]       ;
  1181.                 MOV     CONST_AREA[BX+2],AX ; Save end of area
  1182.                 ADD     CONST_NUM,4     ;
  1183.                 CALL    DISP_SCREEN     ;
  1184.                 RET                     ;
  1185. ;
  1186. ; F7 = Start new field.
  1187. ;
  1188. FSTRT_SUB:                              ; F7
  1189.                 MOV     BX,DEF_NUM      ; Pointer to next field definition
  1190.                 CMP     BX,EDIT_FLD*4   ; Area full?
  1191.                 JAE     DEF_ERROR       ; Yes
  1192.                 CMP     DEF_AREA[BX],0  ; Already started the area?
  1193.                 JNZ     DEF_NEST        ; Yes, cannot nest
  1194.                 MOV     DEF_AREA[BX],SI ; Save start of area
  1195.                 CALL    DISP_SCREEN     ;
  1196.                 RET                     ;
  1197. DEF_ERROR:                              ;
  1198.                 MOV     AX,OFFSET ROOM_MSG ;
  1199.                 MOV     CX,L_ROOM       ;
  1200.                 CALL    STAT_MSG        ; Display error in status line
  1201.                 JMP     EDIT_FILE       ;
  1202. DEF_NEST:                               ;
  1203.                 MOV     AX,OFFSET NEST_MSG ;
  1204.                 MOV     CX,L_NEST       ;
  1205.                 CALL    STAT_MSG        ;
  1206.                 JMP     EDIT_FILE       ;
  1207. ;
  1208. ; F8 = End of new field.
  1209. ;
  1210. FEND_SUB:                               ;
  1211.                 MOV     BX,DEF_NUM      ;
  1212.                 CMP     BX,EDIT_FLD*4   ; Full?
  1213.                 JAE     DEF_ERROR       ;
  1214.                 CMP     DEF_AREA[BX],0  ; Started area?
  1215.                 JZ      DEF_UNBAL       ; No
  1216.                 LEA     AX,[SI+2]       ;
  1217.                 MOV     DEF_AREA[BX+2],AX ; Save end of area
  1218.                 ADD     DEF_NUM,4       ;
  1219.                 CALL    DISP_SCREEN     ;
  1220.                 RET                     ;
  1221. DEF_UNBAL:                              ;
  1222.                 MOV     AX,OFFSET BAL_MSG ;
  1223.                 MOV     CX,L_BAL        ;
  1224.                 CALL    STAT_MSG        ;
  1225.                 JMP     EDIT_FILE       ;
  1226. ;
  1227. ; F9 = Select new colors.
  1228. ;
  1229. ATTR_SUB:                               ;
  1230. ;
  1231. ; Display color menu.
  1232. ;
  1233.                 MOV     CX,L_CTAB       ; Number of lines
  1234.                 MOV     AX,OFFSET COLOR_MNU ;
  1235.                 CALL    DISP_MNU        ; Display attribute menu
  1236. ;
  1237. ; Display status line showing current colors as defaults.
  1238. ;
  1239.                 MOV     AL,[SI+1]       ; Get text color
  1240.                 AND     AL,0FH          ;
  1241.                 CALL    BTD             ;
  1242.                 MOV     WORD PTR TCLR,AX ;
  1243.                 MOV     AL,[SI+1]       ;
  1244.                 MOV     AH,'N'          ; Blink Value
  1245.                 TEST    AL,80H          ; Is it blinking?
  1246.                 JZ      NOT_BLINK       ; No
  1247.                 MOV     AH,'Y'          ;
  1248. NOT_BLINK:                              ;
  1249.                 MOV     BLNK,AH         ;
  1250.                 MOV     CL,4            ;
  1251.                 SHR     AL,CL           ;
  1252.                 AND     AL,7            ; Background color
  1253.                 CALL    BTD             ;
  1254.                 MOV     BCLR,AH         ;
  1255. ;
  1256. ; Get new color values.
  1257. ;
  1258.                 PUSH    SI              ;
  1259.                 MOV     DH,SCR_LIN      ;
  1260.                 DEC     DH              ;
  1261. COLOR_ST:                               ;
  1262.                 MOV     DL,OFFSET STAT_Q - OFFSET STATUS_MSG ;
  1263.                 ADD     DL,OFFSET TCLR - OFFSET COLOR_MSG ;
  1264.                 MOV     SI,OFFSET TCLR  ;
  1265.                 XOR     BH,BH           ;
  1266. COLOR_LP:                               ;
  1267.                 MOV     AX,OFFSET COLOR_MSG ; Put in status line
  1268.                 MOV     CX,L_COLOR      ;
  1269.                 CALL    STAT_MSG        ;
  1270.                 MOV     AH,CRS$         ;
  1271.                 INT     VIDEO$          ; Set cursor position
  1272.                 XOR     AH,AH           ;
  1273.                 INT     KYBD$           ; Get next input
  1274.                 CMP     AL,'0'          ; Digit?
  1275.                 JB      NOT_CDIG        ; No
  1276.                 CMP     AL,'9'          ;
  1277.                 JA      NOT_CDIG        ;
  1278.                 CMP     SI,OFFSET BCLR  ; Blink field?
  1279.                 JA      COLOR_LP        ; Yes, no digits
  1280.                 MOV     [SI],AL         ; Put digit
  1281.                 CMP     SI,OFFSET TCLR  ; Moving to another field?
  1282.                 JA      PUT_CLR2        ;
  1283.                 INC     SI              ;
  1284.                 INC     DL              ;
  1285.                 JMP     COLOR_LP        ;
  1286. PUT_CLR2:                               ;
  1287.                 CMP     SI,OFFSET BCLR  ; Moving to blink field?
  1288.                 JAE     PUT_BKGR        ; Yes
  1289.                 ADD     SI,OFFSET BCLR - OFFSET TCLR - 1 ;
  1290.                 ADD     DL,OFFSET BCLR - OFFSET TCLR - 1 ;
  1291.                 JMP     COLOR_LP        ;
  1292. PUT_BKGR:                               ;
  1293.                 ADD     SI,OFFSET BLNK - OFFSET BCLR ;
  1294.                 ADD     DL,OFFSET BLNK - OFFSET BCLR ;
  1295.                 JMP     COLOR_LP        ;
  1296. NOT_CDIG:                               ;
  1297.                 CMP     AL,ESC_CHR      ; Quit?
  1298.                 JE      CLR_QUIT        ;
  1299.                 CMP     AL,CR_CHR       ; Done?
  1300.                 JE      CLR_DONE        ; Yes
  1301.                 CMP     AL,BS_CHR       ; Backspace?
  1302.                 JE      CLR_BS          ; Yes
  1303.                 CMP     SI,OFFSET BLNK  ; Blink field?
  1304.                 JNE     COLOR_LP        ; No
  1305.                 AND     AL,NOT 20H      ;
  1306.                 CMP     AL,'N'          ;
  1307.                 JE      PUT_BLNK        ;
  1308.                 CMP     AL,'Y'          ;
  1309.                 JNE     COLOR_LP        ;
  1310. PUT_BLNK:                               ;
  1311.                 MOV     [SI],AL         ;
  1312.                 JMP     COLOR_LP        ;
  1313. ;
  1314. ; We have the color request.  Convert the values and check if legal.
  1315. ;
  1316. CLR_DONE:                               ;
  1317.                 MOV     AL,TCLR         ; Convert foreground color to binary
  1318.                 SUB     AL,'0'          ;
  1319.                 MUL     C10             ;
  1320.                 ADD     AL,TCLR+1       ;
  1321.                 SUB     AL,'0'          ;
  1322.                 MOV     AH,BCLR         ; Convert background color
  1323.                 SUB     AH,'0'          ;
  1324.                 CMP     AL,15           ; Legal colors?
  1325.                 JA      GO_CST          ; No
  1326.                 CMP     AH,7            ;
  1327.                 JA      GO_CST          ;
  1328.                 MOV     CL,4            ; Put in attribute format
  1329.                 SHL     AH,CL           ;
  1330.                 OR      AL,AH           ;
  1331.                 CMP     BLNK,'Y'        ; Blink?
  1332.                 JNE     NOT_BLNK        ; No
  1333.                 OR      AL,80H          ;
  1334. NOT_BLNK:                               ;
  1335.                 MOV     ATTRIBUTE,AL    ; Save new attribute
  1336. CLR_QUIT:                               ;
  1337.                 POP     SI              ;
  1338.                 CALL    DISP_SCREEN     ; Redisplay screen
  1339.                 JMP     EDIT_STATUS     ; Redisplay cursor
  1340. ;
  1341. ; Handle backspacing in color information.
  1342. ;
  1343. CLR_BS:                                 ;
  1344.                 CMP     SI,OFFSET TCLR+1 ; In first field?
  1345.                 JA      BS_BKGR         ; No
  1346.                 JB      GO_CLRLP        ;
  1347.                 DEC     SI              ;
  1348.                 DEC     DL              ;
  1349. GO_CLRLP:                               ;
  1350.                 JMP     COLOR_LP        ;
  1351. BS_BKGR:                                ;
  1352.                 CMP     SI,OFFSET BCLR  ; In background?
  1353.                 JA      BS_BLNK         ; No
  1354.                 SUB     SI,OFFSET BCLR - OFFSET TCLR - 1 ;
  1355.                 SUB     DL,OFFSET BCLR - OFFSET TCLR - 1 ;
  1356.                 JMP     COLOR_LP        ;
  1357. BS_BLNK:                                ;
  1358.                 SUB     SI,OFFSET BLNK - OFFSET BCLR ;
  1359.                 SUB     DL,OFFSET BLNK - OFFSET BCLR ;
  1360.                 JMP     COLOR_LP        ;
  1361. GO_CST:                                 ;
  1362.                 JMP     COLOR_ST        ;
  1363. ;
  1364. ; F10 = Put new attribute in character and advance cursor.
  1365. ;
  1366. COLOR_SUB:                              ;
  1367.                 MOV     AH,ATTRIBUTE    ;
  1368.                 MOV     [SI+1],AH       ; Put new attribute
  1369.                 MOV     AL,[SI]         ;
  1370.                 JMP     EDIT_NINS       ; Redisplay the character position
  1371. ;
  1372. ; Alt= = Put next key value whatever it is.
  1373. ;
  1374. FORCE_SUB:                              ;
  1375.                 XOR     AH,AH           ;
  1376.                 INT     KYBD$           ; Get next key stroke
  1377.                 JMP     EDIT_FORCE      ; and force into file
  1378. ;
  1379. ; Ctrl Enter = Done
  1380. ;
  1381. CENTER_SUB:                             ; Ctrl Enter = Done
  1382.                 POP     AX              ; Throw away return
  1383.                 CALL    REST_VID        ; Restore screen
  1384.                 CALL    GET_TIME        ; Initialize date & time variables
  1385. ;
  1386. ; Read template file.
  1387. ;
  1388.                 MOV     BX,TEMPLFILE    ; Read template file
  1389.                 MOV     IN_CNT,0        ; Start new buffer
  1390.                 MOV     AH,SCR_ATTR     ; Starting attribute for ANSI conversion
  1391.                 MOV     DX,1            ; First field for screen file editing
  1392.                 CMP     EOPT,L_EDIT     ; Editing a screen file?
  1393.                 JE      DO_INP          ; Yes, go copy the screen
  1394.                 CMP     BX,0            ; Any template file?
  1395.                 JZ      GO_DONE         ; No
  1396. ;
  1397. ; Scan template file looking for.  Check character type and handle as needed.
  1398. ;
  1399. TMPL_LP:                                ;
  1400.                 CALL    GET_CHR         ; Get next character
  1401.                 JNZ     TMPL_OK         ; Got a character
  1402. GO_DONE:                                ;
  1403.                 JMP     WF_DONE         ;
  1404. TMPL_OK:                                ;
  1405.                 MOV     CX,L_TCHR       ;
  1406.                 MOV     SI,OFFSET TMPL_CHR ;
  1407.                 CALL    TBL_SRCH        ; Find character type
  1408.                 JMP     TMPL_VECT[SI]   ; Switch on character type
  1409. TMPL_PUT:                               ;
  1410.                 CALL    OUT_CHR         ; No, send character to output
  1411.                 JMP     TMPL_LP         ; Continue processing characters
  1412. ;
  1413. ; \ Force out next character.
  1414. ;
  1415. TMPL_FORCE:                             ;
  1416.                 CALL    GET_CHR         ; Get character
  1417.                 JNZ     TMPL_PUT        ; If none, error.  Otherwise put it
  1418. ;
  1419. ; Bad template file format.
  1420. ;
  1421. TMPL_ERROR:                             ;
  1422.                 MOV     CX,L_TBAD       ;
  1423.                 MOV     DX,OFFSET TMPL_MSG ;
  1424.                 JMP     ERROR_DSP       ;
  1425. ;
  1426. ; < Switch output files.
  1427. ;
  1428. TMPL_FILE:                              ;
  1429.                 CALL    DTB             ; Get file number
  1430.                 CMP     AL,'>'          ;
  1431.                 JNE     TMPL_ERROR      ; Not correct closing symbol
  1432.                 DEC     DX              ;
  1433.                 MOV     SI,DX           ;
  1434.                 SHL     SI,1            ;
  1435.                 CMP     DX,NUM_OUT      ; Legal value?
  1436.                 JAE     TMPL_ERROR      ;
  1437.                 CALL    WR_OUT          ; Spill rest of buffer for current file
  1438.                 MOV     OUT_INDX,0      ;
  1439.                 MOV     AX,OUT_HNDL[SI] ; Get handle
  1440.                 MOV     OUTFILE,AX      ;
  1441.                 JMP     TMPL_LP         ;
  1442. ;
  1443. ; [ Look for pattern type.
  1444. ;
  1445. TMPL_SENT:                              ;
  1446. ;
  1447. ; Check for an input area reference.
  1448. ;
  1449.                 CALL    DTB             ; Convert value to binary
  1450.                 OR      DX,DX           ; Input number?
  1451.                 JNZ     DO_INP          ;
  1452.                 JMP     CHK_PAT         ; No, check if time/date pattern
  1453. ;
  1454. ; We have an input area to copy.  Check to see if the number is good.
  1455. ;
  1456. DO_INP:                                 ;
  1457.                 DEC     DX              ;
  1458.                 SHL     DX,1            ; Convert to area index
  1459.                 SHL     DX,1            ;
  1460.                 CMP     DX,EDIT_NUM     ; Legal area?
  1461.                 JAE     TMPL_ERROR      ; No, error
  1462. ;
  1463. ; Get area to copy.
  1464. ; We will not copy trailing blanks from the input area.
  1465. ; Input will be treated as a single character string with no CR,LFs inserted.
  1466. ; The template may indicate formatting by following the number with any of
  1467. ; the following pattern characters:
  1468. ; ]     =       All remaining input characters
  1469. ; ?     =       Next input character
  1470. ; =     =       All input characters up to end of screen line
  1471. ; |     =       Ignore rest of template if no more input
  1472. ; \     =       Include next template character in output
  1473. ; All other characters in the template are copied to the output.
  1474. ;
  1475.                 MOV     DI,DX           ; Input area index
  1476.                 MOV     DX,EDIT_AREA[DI] ; Start of input area
  1477.                 MOV     DI,EDIT_AREA[DI+2] ; End of input area
  1478. ;
  1479. ; Find last non-blank.
  1480. ;
  1481.                 CALL    TRIM            ; Find start of trailing spaces
  1482.                 XCHG    DX,DI           ; DX=End, DI=Start
  1483. ;
  1484. ; Scan template doing the replacement.
  1485. ;
  1486.                 CMP     EOPT,L_EDIT     ; Editing a screen file?
  1487.                 JNE     REPL_FIRST      ; Already have first character
  1488.                 JMP     COPY_SCRN       ; Yes
  1489. REPL_INP:                               ;
  1490.                 CALL    GET_CHR         ; Get next template character
  1491.                 JZ      TMPL_ERROR      ;
  1492. REPL_FIRST:                             ;
  1493.                 MOV     CX,L_RCHR       ;
  1494.                 MOV     SI,OFFSET REPL_CHR ;
  1495.                 CALL    TBL_SRCH        ; Get character type
  1496.                 CALL    REPL_VECT[SI]   ; Switch on character type
  1497.                 JMP     REPL_INP        ;
  1498. ;
  1499. ; All non-pattern characters.
  1500. ;
  1501. REPL_PUT:                               ;
  1502.                 CALL    OUT_CHR         ; Just send the character to output
  1503. REPL_OK:                                ;
  1504.                 RET                     ; Continue replacing
  1505. GO_STOP:                                ;
  1506.                 JMP     COPY_STOP       ;
  1507. ;
  1508. ; \ Copy the next template character.
  1509. ;
  1510. COPY_FORCE:                             ;
  1511.                 CALL    GET_CHR         ; Get the character
  1512.                 JZ      TMPL_ERROR      ;
  1513.                 JMP     REPL_PUT        ;
  1514. ;
  1515. ; ? Copy the next input character.
  1516. ;
  1517. COPY_ONE:                               ;
  1518.                 CMP     DI,DX           ; Any left?
  1519.                 JAE     REPL_OK         ; No, nothing to copy
  1520.                 MOV     AL,[DI]         ;
  1521.                 INC     DI              ;
  1522.                 INC     DI              ;
  1523.                 JMP     REPL_PUT        ;
  1524. ;
  1525. ; Copy to file in screen file format.  Generate ANSI sequences as needed.
  1526. ; For start and end of defined input fields insert [ and ].
  1527. ; For start and end of constant fields insert { and }.
  1528. ; Put a \ in front of screen file control characters that appear as data.
  1529. ;
  1530. COPY_SCRN:                              ;
  1531.                 CMP     DX,SCRN_END     ; Past user defined end?
  1532.                 JBE     COPY_SOK        ; No
  1533.                 MOV     DX,SCRN_END     ;
  1534.                 INC     DX              ;
  1535.                 INC     DX              ;
  1536. COPY_SOK:                               ;
  1537.                 CALL    COPY_LINE       ; Copy one line
  1538.                 MOV     AL,CR_CHR       ;
  1539.                 CALL    OUT_CHR         ;
  1540.                 MOV     AL,LF_CHR       ; Put end of line
  1541.                 CALL    OUT_CHR         ;
  1542.                 CMP     DI,DX           ; Any input left?
  1543.                 JB      COPY_SOK        ; Yes
  1544.                 JMP     WF_DONE         ; No
  1545. ;
  1546. ; = Copy all input characters up to the end of the screen line.
  1547. ; Do not copy trailing blanks on the screen line but do skip over them.
  1548. ;
  1549. COPY_LINE:                              ;
  1550.                 PUSH    CX              ;
  1551.                 PUSH    AX              ;
  1552.                 MOV     AX,DI           ; Starting location
  1553.                 SUB     AX,OFFSET EDIT_LOC ; Index
  1554.                 SHR     AX,1            ; Convert to character index
  1555.                 MOV     CX,WORD PTR SCR_COL ; Columns per line
  1556.                 DIV     CL              ;
  1557.                 SUB     CL,AH           ; Remaining characters to end of line
  1558.                 MOV     AX,DX           ;
  1559.                 SUB     AX,DI           ;
  1560.                 SHR     AX,1            ; Remaining characters in input field
  1561.                 CMP     AX,CX           ; Use lesser
  1562.                 JAE     LINE_COPY       ;
  1563.                 MOV     CX,AX           ;
  1564. LINE_COPY:                              ;
  1565.                 POP     AX              ;
  1566.                 JCXZ    LINE_DONE       ;
  1567.                 PUSH    DX              ;
  1568.                 MOV     DX,DI           ; Start of area
  1569.                 ADD     DI,CX           ; End of input area to be copied
  1570.                 ADD     DI,CX           ;
  1571.                 PUSH    DI              ; Save end
  1572.                 CALL    TRIM            ; Ignore trailing blanks
  1573.                 MOV     CX,DI           ; Compute new length
  1574.                 SUB     CX,DX           ;
  1575.                 SHR     CX,1            ;
  1576.                 MOV     DI,DX           ; Start of copy
  1577.                 JCXZ    LINE_MT         ; All blank line
  1578. ;
  1579. ; Now copy the characters checking for start and end of input areas and
  1580. ; change of attributes.
  1581. ;
  1582. LINE_CP:                                ;
  1583.                 CMP     EOPT,L_EDIT     ; Generating screen file?
  1584.                 JNE     LINE_PUT        ; No
  1585.                 MOV     AL,'['          ; Do start of fields
  1586.                 CALL    FIELD_GEN       ; Check for field start
  1587.                 CMP     AH,[DI+1]       ; Attributes match?
  1588.                 JNE     GEN_ANSI        ; No, generate ANSI sequence
  1589. LINE_CHR:                               ;
  1590.                 MOV     DX,CX           ;
  1591.                 MOV     AL,[DI]         ; Get next input character
  1592.                 MOV     CX,L_SCHR       ; See if this is a screen control char
  1593.                 MOV     SI,OFFSET SCR_CHR ;
  1594.                 CALL    TBL_SRCH        ;
  1595.                 MOV     CX,DX           ;
  1596.                 CMP     SI,0            ; Normal character?
  1597.                 JZ      LINE_PUT        ; Yes
  1598.                 MOV     DL,AL           ;
  1599.                 MOV     AL,'\'          ; Send force character
  1600.                 CALL    OUT_CHR         ;
  1601.                 MOV     AL,DL           ;
  1602. LINE_PUT:                               ;
  1603.                 MOV     AL,[DI]         ; Get next input character
  1604.                 CALL    OUT_CHR         ; Send to output
  1605.                 INC     DI              ;
  1606.                 INC     DI              ;
  1607.                 CMP     EOPT,L_EDIT     ; Screen file editing?
  1608.                 JNE     LINE_ELP        ; No
  1609.                 MOV     AL,']'          ; Do end of fields
  1610.                 CALL    FIELD_GEN       ;
  1611. LINE_ELP:                               ;
  1612.                 LOOP    LINE_CP         ;
  1613. LINE_MT:                                ;
  1614.                 POP     DI              ; Move to end of line
  1615.                 POP     DX              ;
  1616. LINE_DONE:                              ;
  1617.                 POP     CX              ;
  1618.                 RET                     ;
  1619. ;
  1620. ; Generate ANSI sequence from change in attribute.
  1621. ;
  1622. GEN_ANSI:                               ;
  1623.                 PUSH    CX              ;
  1624.                 PUSH    DX              ;
  1625.                 XOR     CX,CX           ; No values output yet
  1626. ;
  1627. ; Put Esc [ start of ANSI sequence.
  1628. ;
  1629.                 MOV     AL,ESC_CHR      ; Start ANSI sequence
  1630.                 CALL    OUT_CHR         ;
  1631.                 MOV     AL,'['          ;
  1632.                 CALL    OUT_CHR         ;
  1633. ;
  1634. ; Check to see if foreground colors are changed.
  1635. ;
  1636.                 MOV     DL,[DI+1]       ; Isolate foregrounds
  1637.                 MOV     DH,AH           ;
  1638.                 AND     DX,0F0FH        ;
  1639.                 CMP     DL,DH           ; Did foreground change?
  1640.                 JE      NOT_FORE        ; No
  1641.                 AND     DL,7            ; Check to see if only intensity
  1642.                 CMP     DL,DH           ;
  1643.                 JE      SET_INT         ; Only intensity being set
  1644.                 TEST    DL,5            ; Switch attributes if appropriate
  1645.                 JPE     NSW_1           ;
  1646.                 XOR     DL,5            ; Invert attributes
  1647. NSW_1:                                  ;
  1648.                 MOV     AL,'3'          ; Put foreground color
  1649.                 CALL    OUT_CHR         ;
  1650.                 MOV     AL,DL           ;
  1651.                 ADD     AL,'0'          ;
  1652.                 CALL    OUT_CHR         ;
  1653.                 INC     CX              ;
  1654. ;
  1655. ; Foreground changed, so check to see if we need to set high intensity.
  1656. ;
  1657.                 MOV     DL,[DI+1]       ;
  1658.                 TEST    DL,8            ; High intensity set?
  1659.                 JZ      NOT_FORE        ; No
  1660.                 MOV     AL,';'          ;
  1661.                 CALL    OUT_CHR         ;
  1662. SET_INT:                                ;
  1663.                 MOV     AL,'1'          ;
  1664.                 CALL    OUT_CHR         ;
  1665.                 INC     CX              ;
  1666. NOT_FORE:                               ;
  1667.                 MOV     DH,AH           ;
  1668.                 MOV     DL,[DI+1]       ; Compare backgrounds
  1669.                 AND     DX,7070H        ;
  1670.                 CMP     DL,DH           ; Did background change?
  1671.                 JE      NOT_BKGR        ; No
  1672.                 TEST    DL,50H          ; Switch attributes if appropriate
  1673.                 JPE     NSW_2           ;
  1674.                 XOR     DL,50H          ;
  1675. NSW_2:                                  ;
  1676.                 JCXZ    NO_SEP2         ; No value output yet
  1677.                 MOV     AL,';'          ; Put separator
  1678.                 CALL    OUT_CHR         ;
  1679. NO_SEP2:                                ;
  1680.                 MOV     AL,'4'          ;
  1681.                 CALL    OUT_CHR         ; Put background color
  1682.                 MOV     AL,DL           ;
  1683.                 MOV     CL,4            ;
  1684.                 SHR     AL,CL           ;
  1685.                 ADD     AL,'0'          ;
  1686.                 CALL    OUT_CHR         ;
  1687. NOT_BKGR:                               ;
  1688.                 TEST    BYTE PTR [DI+1],80H ; Blink set?
  1689.                 JZ      NOT_BLI         ; No
  1690.                 JCXZ    NO_SEP3         ;
  1691.                 MOV     AL,';'          ; Separator
  1692.                 CALL    OUT_CHR         ;
  1693. NO_SEP3:                                ;
  1694.                 MOV     AL,'5'          ;
  1695.                 CALL    OUT_CHR         ;
  1696. NOT_BLI:                                ;
  1697.                 MOV     AL,'m'          ; Put terminator
  1698.                 CALL    OUT_CHR         ;
  1699.                 MOV     AH,[DI+1]       ; New attribute
  1700.                 POP     DX              ;
  1701.                 POP     CX              ;
  1702.                 JMP     LINE_CHR        ;
  1703. ;
  1704. ; | Stop copying from this template if there is no more input.
  1705. ;
  1706. COPY_STOP:                              ;
  1707.                 CMP     DI,DX           ; Any more input?
  1708.                 JAE     COPY_SKIP       ; No
  1709.                 RET                     ; Yes
  1710. COPY_SKIP:                              ;
  1711.                 CALL    GET_CHR         ; Skip to end of template
  1712.                 JZ      BAD_TP          ;
  1713.                 CMP     AL,']'          ; End of template?
  1714.                 JE      COPY_DONE       ; Yes
  1715.                 CMP     AL,'\'          ; Force?
  1716.                 JNE     COPY_SKIP       ; No, keep looking
  1717.                 CALL    GET_CHR         ; Ignore next character
  1718.                 JZ      BAD_TP          ;
  1719.                 JMP     COPY_SKIP       ; Keep looking
  1720. ;
  1721. ; ] Copy remaining input characters to output and then start over at top.
  1722. ;
  1723. COPY_REST:                              ;
  1724.                 CMP     DI,DX           ; Any remaining input characters?
  1725.                 JAE     COPY_DONE       ; No
  1726.                 MOV     AL,[DI]         ;
  1727.                 CALL    OUT_CHR         ; Copy to output
  1728.                 INC     DI              ;
  1729.                 INC     DI              ;
  1730.                 JMP     COPY_REST       ;
  1731. BAD_TP:                                 ;
  1732.                 POP     AX              ;
  1733.                 JMP     TMPL_ERROR      ;
  1734. COPY_DONE:                              ;
  1735.                 POP     AX              ;
  1736.                 JMP     TMPL_LP         ; Continue working on template file
  1737. ;
  1738. ; Check for time and date patterns.
  1739. ; \ Force next character
  1740. ; MM DD CC YY DW MN hh mm ss are all replaced with appropriate values.
  1741. ;
  1742. CHK_PAT:                                ;
  1743.                 PUSH    AX              ;
  1744. CHK_MORE:                               ;
  1745.                 CMP     AL,']'          ; End sentinel?
  1746.                 JE      COPY_DONE       ; Yes, look for next template
  1747.                 MOV     AH,AL           ; Save first pattern character
  1748.                 CALL    GET_CHR         ; Get second pattern character
  1749.                 JZ      BAD_TP          ;
  1750. PAT_CHK:                                ;
  1751.                 CMP     AH,'\'          ; Force next character?
  1752.                 JE      PAT_NEXT        ; Yes
  1753.                 MOV     SI,OFFSET TD_TAB ; Pattern table
  1754.                 MOV     CX,L_TD         ;
  1755.                 CALL    WTBL_SRCH       ; Find matching entry
  1756.                 CMP     SI,0            ; Do we have a pattern?
  1757.                 JNZ     REPL_PAT        ; Yes
  1758.                 XCHG    AL,AH           ; No, output first char and continue
  1759.                 CALL    OUT_CHR         ; Send character to output
  1760.                 XCHG    AL,AH           ;
  1761.                 JMP     CHK_MORE        ; Keep checking for patterns
  1762. ;
  1763. ; \ Found a force character.
  1764. ;
  1765. PAT_NEXT:                               ;
  1766.                 CALL    OUT_CHR         ; Send forced character to output
  1767. PAT_GET:                                ;
  1768.                 CALL    GET_CHR         ;
  1769.                 JZ      BAD_TP          ;
  1770.                 JMP     CHK_MORE        ;
  1771. ;
  1772. ; Found a pattern to be replaced.
  1773. ; Check for DW and MN case and handle specially.
  1774. ;
  1775. REPL_PAT:                               ;
  1776.                 MOV     DI,TD_LOC[SI-2] ; Data loc
  1777.                 CMP     SI,4            ; DW or MN?
  1778.                 JE      CK_MON          ; MN
  1779.                 JB      CK_DOW          ; DW
  1780. DO_2:                                   ;
  1781.                 MOV     AX,[DI]         ; Get data
  1782.                 CALL    OUT_CHR         ; Put in output
  1783.                 MOV     AL,AH           ;
  1784.                 CALL    OUT_CHR         ;
  1785.                 JMP     PAT_GET         ;
  1786. CK_MON:                                 ;
  1787.                 MOV     AX,OFFSET MON_TAB ; Month abbreviation table
  1788. DO_3:                                   ;
  1789.                 ADD     AX,[DI]         ;
  1790.                 MOV     DI,AX           ;
  1791.                 MOV     AL,[DI]         ; Get abbreviation
  1792.                 CALL    OUT_CHR         ; Put first character
  1793.                 INC     DI              ;
  1794.                 JMP     DO_2            ;
  1795. CK_DOW:                                 ;
  1796.                 MOV     AX,OFFSET DOW_TAB ; Day of week abbreviation table
  1797.                 JMP     DO_3            ;
  1798. ;
  1799. ; { Constant area reference.
  1800. ;
  1801. TMPL_CONST:                             ;
  1802.                 CALL    DTB             ; Convert value to binary
  1803.                 OR      DX,DX           ; Constant number?
  1804.                 JNZ     DO_CONST        ;
  1805.                 CMP     AL,'['          ; Indirect reference?
  1806.                 JE      DO_INDIR        ; Indirect constant reference
  1807.                 JMP     TMPL_ERROR      ; Incorrect constant reference
  1808. ;
  1809. ; We have {[nnn]}.
  1810. ;
  1811. DO_INDIR:                               ;
  1812.                 CALL    DTB             ; Get input field reference
  1813.                 OR      DX,DX           ; Got a number?
  1814.                 JZ      GO_TERR         ; Yes
  1815.                 CMP     AL,']'          ; Closed properly?
  1816.                 JE      INDIR_OK        ;
  1817. GO_TERR:                                ;
  1818.                 JMP     TMPL_ERROR      ;
  1819. INDIR_OK:                               ;
  1820.                 DEC     DX              ;
  1821.                 SHL     DX,1            ;
  1822.                 SHL     DX,1            ;
  1823.                 CMP     DX,EDIT_NUM     ; Legal field reference?
  1824.                 JAE     GO_TERR         ; No
  1825.                 MOV     SI,DX           ;
  1826.                 MOV     CX,EDIT_AREA[SI+2] ; End of area
  1827.                 MOV     SI,EDIT_AREA[SI] ; Start of input
  1828.                 XOR     DX,DX           ;
  1829. INDIR_VAL:                              ;
  1830.                 LODSB                   ; Get next character
  1831.                 CMP     AL,'0'          ; If not a digit, skip
  1832.                 JB      INDIR_SKIP      ;
  1833.                 CMP     AL,'9'          ;
  1834.                 JA      INDIR_SKIP      ;
  1835.                 SUB     AL,'0'          ; Convert to binary
  1836.                 XCHG    AL,DL           ;
  1837.                 MUL     C10             ;
  1838.                 ADD     DX,AX           ;
  1839. INDIR_SKIP:                             ;
  1840.                 INC     SI              ;
  1841.                 CMP     SI,CX           ;
  1842.                 JB      INDIR_VAL       ;
  1843.                 CALL    GET_CHR         ; Must have closing brace
  1844.                 JZ      GO_TERR         ;
  1845. ;
  1846. ; We have a constant reference.
  1847. ;
  1848. DO_CONST:                               ;
  1849.                 CMP     AL,'}'          ; Closing brace?
  1850.                 JNE     GO_TERR         ;
  1851.                 DEC     DX              ;
  1852.                 SHL     DX,1            ;
  1853.                 SHL     DX,1            ;
  1854.                 CMP     DX,CONST_NUM    ; Legal constant reference?
  1855.                 JAE     GO_TMPL         ; No, ignore
  1856.                 MOV     SI,DX           ;
  1857.                 MOV     DX,CONST_AREA[SI+2] ; End of constant area
  1858.                 MOV     SI,CONST_AREA[SI] ; Start of constant
  1859. CONST_LP:                               ;
  1860.                 LODSB                   ;
  1861.                 CALL    OUT_CHR         ; Send next constant character
  1862.                 INC     SI              ;
  1863.                 CMP     SI,DX           ; Reached the end?
  1864.                 JB      CONST_LP        ; No
  1865. GO_TMPL:                                ;
  1866.                 JMP     TMPL_LP         ; Yes, continue processing template
  1867. ;
  1868. ; Processing complete.
  1869. ;
  1870. WF_DONE:                                ;
  1871.                 CALL    WR_OUT          ; Write remaining buffered output
  1872.                 MOV     CX,NUM_OUT      ; Number of output files
  1873.                 XOR     SI,SI           ;
  1874. CLOSE_LP:                               ;
  1875.                 MOV     BX,OUT_HNDL[SI] ; Close output file
  1876.                 MOV     AH,CLOSE$       ;
  1877.                 INT     DOS$            ;
  1878.                 INC     SI              ;
  1879.                 INC     SI              ;
  1880.                 LOOP    CLOSE_LP        ;
  1881.                 JMP     SHORT EXIT_DOS  ;
  1882. ;
  1883. ; Esc = Quit
  1884. ;
  1885. ESC_SUB:                                ; Esc
  1886.                 MOV     AX,OFFSET Q_MSG ;
  1887.                 MOV     CX,L_Q          ;
  1888.                 CALL    STAT_MSG        ; Display query "Really want to quit?"
  1889. Q_SOL:                                  ;
  1890.                 XOR     AH,AH           ;
  1891.                 INT     KYBD$           ; Read next character
  1892.                 AND     AL,NOT 20H      ; Make upper case
  1893.                 CMP     AL,'Y'          ; Really want to exit?
  1894.                 JE      DO_QUIT         ; Yes
  1895.                 CMP     AL,'N'          ; Want to keep going?
  1896.                 JNE     Q_SOL           ; No, resolicit
  1897.                 JMP     EDIT_STATUS     ; Keep on going
  1898. DO_QUIT:                                ;
  1899.                 CALL    REST_VID        ; Restore original screen
  1900. EXIT_DOS:                               ;
  1901.                 MOV     AH,EXIT$        ; Return to DOS
  1902.                 XOR     AL,AL           ; Normal exit
  1903.                 INT     DOS$            ;
  1904. ;
  1905. ; Commnon code for error message display and error exit to DOS.
  1906. ;
  1907. ERROR_DSP:                              ;
  1908.                 MOV     AH,WRFILE$      ; Display error message
  1909.                 MOV     BX,ERROUT       ;
  1910.                 INT     DOS$            ;
  1911.                 MOV     CX,2            ;
  1912.                 MOV     DX,OFFSET CRLF  ; Skip a line
  1913.                 MOV     AH,WRFILE$      ;
  1914.                 INT     DOS$            ;
  1915.                 MOV     AH,EXIT$        ;
  1916.                 MOV     AL,1            ; Error exit
  1917.                 INT     DOS$            ;
  1918. ;
  1919. ;
  1920. ; PROCEDURE FIND_AREA
  1921. ;
  1922. ; FIND_AREA finds the input area containing the current cursor position.
  1923. ; If the position is not in an area, the next logical area start is
  1924. ; returned.
  1925. ;
  1926. ; INPUT:
  1927. ;       SI      =       Current cursor location
  1928. ;
  1929. ; OUTPUT:
  1930. ;       BX      =       Pointer to area table entry
  1931. ;       CF      =       1, Not in the area
  1932. ;                       0, In the area
  1933. ;
  1934. FIND_AREA       PROC                    ;
  1935.                 XOR     BX,BX           ; Search input table
  1936. FA_LP:                                  ;
  1937.                 CMP     BX,EDIT_NUM     ; Still in table?
  1938.                 JA      FA_FIRST        ; No, go to home position
  1939.                 CMP     SI,EDIT_AREA[BX] ; Within this area?
  1940.                 JB      FA_NOT          ; No
  1941.                 CMP     SI,EDIT_AREA[BX+2] ;
  1942.                 JB      FA_IN           ; Yes
  1943.                 ADD     BX,4            ; Try next area
  1944.                 JMP     FA_LP           ;
  1945. FA_FIRST:                               ;
  1946.                 XOR     BX,BX           ;
  1947. FA_NOT:                                 ;
  1948.                 CLC                     ;
  1949. FA_IN:                                  ;
  1950.                 CMC                     ; Set carry appropriately
  1951.                 RET                     ;
  1952. FIND_AREA       ENDP                    ;
  1953. ;
  1954. ;
  1955. ; PROCEDURE: DISP_MNU
  1956. ;
  1957. ; DISP_MNU displays a Nx40 menu on the screen.
  1958. ;
  1959. ; INPUT:
  1960. ;       AX      =       Menu location
  1961. ;       CX      =       Number of lines in menu
  1962. ;
  1963. ; OUTPUT:
  1964. ;       AX, CX contents destroyed.
  1965. ;
  1966. DISP_MNU        PROC                    ;
  1967.                 PUSH    DX              ;
  1968.                 PUSH    DI              ;
  1969.                 PUSH    SI              ;
  1970.                 XOR     DI,DI           ;
  1971.                 MOV     DX,CX           ; Number of lines
  1972.                 MOV     SI,AX           ; Start of menu
  1973. DM_LINE:                                ;
  1974.                 MOV     CX,40           ;
  1975. DM_LP:                                  ;
  1976.                 LODSW                   ;
  1977.                 CALL    WRITE_SCREEN    ; Display next character
  1978.                 LOOP    DM_LP           ;
  1979.                 ADD     DI,WORD PTR SCR_COL ; New line
  1980.                 ADD     DI,WORD PTR SCR_COL ;
  1981.                 SUB     DI,80           ;
  1982.                 DEC     DX              ;
  1983.                 JNZ     DM_LINE         ;
  1984.                 POP     SI              ;
  1985.                 POP     DI              ;
  1986.                 POP     DX              ;
  1987.                 RET                     ;
  1988. DISP_MNU        ENDP                    ;
  1989. ;
  1990. ;
  1991. ; PROCEDURE STATUS
  1992. ;
  1993. ; Display status line.
  1994. ;
  1995. ; INPUT:
  1996. ;       DI      =       Current cursor position
  1997. ;       SI      =       Current file position
  1998. ;
  1999. ; OUTPUT:
  2000. ;       AX contents are destroyed.
  2001. ;
  2002. STATUS          PROC                    ;
  2003.                 PUSH    CX              ;
  2004.                 PUSH    DX              ;
  2005.                 PUSH    DI              ;
  2006.                 PUSH    SI              ;
  2007. ;
  2008. ; Convert row and column to ASCII and store in status line.
  2009. ;
  2010.                 MOV     AX,DI           ;
  2011.                 SHR     AX,1            ;
  2012.                 DIV     SCR_COL         ; Get column and row
  2013.                 MOV     CL,AH           ; Save column
  2014.                 XOR     AH,AH           ;
  2015.                 INC     AL              ;
  2016.                 MOV     DI,OFFSET STAT_ROW ;
  2017.                 CALL    BTD3            ; Convert and store row
  2018.                 MOV     AL,CL           ;
  2019.                 INC     AL              ;
  2020.                 XOR     AH,AH           ;
  2021.                 MOV     DI,OFFSET STAT_COL ;
  2022.                 CALL    BTD3            ;
  2023. ;
  2024. ; Convert file line number and put in status.
  2025. ;
  2026.                 LEA     AX,[SI-(OFFSET EDIT_LOC - OFFSET MENU_PSP)] ;
  2027.                 SHR     AX,1            ;
  2028.                 CWD                     ;
  2029.                 DIV     WORD PTR SCR_COL ; Get line number
  2030.                 INC     AX              ; Start at 1
  2031.                 MOV     DI,OFFSET STAT_LIN ;
  2032.                 CALL    BTD3            ; Convert high order
  2033. ;
  2034. ; Display status line.
  2035. ;
  2036.                 MOV     AH,STAT_ATTR    ; Status display attribute
  2037.                 MOV     SI,OFFSET STATUS_MSG ;
  2038.                 MOV     DI,DISP_SIZE    ;
  2039.                 MOV     CX,WORD PTR SCR_COL ;
  2040. STAT_LP:                                ;
  2041.                 LODSB                   ;
  2042.                 CALL    WRITE_SCREEN    ;
  2043.                 LOOP    STAT_LP         ;
  2044.                 POP     SI              ;
  2045.                 POP     DI              ;
  2046.                 POP     DX              ;
  2047.                 POP     CX              ;
  2048.                 RET                     ;
  2049. STATUS          ENDP                    ;
  2050. ;
  2051. ;
  2052. ; PROCEDURE: STAT_MSG
  2053. ;
  2054. ; STAT_MSG displays a message in the status field.
  2055. ;
  2056. ; INPUT:
  2057. ;       AX      =       Start of message to display
  2058. ;       CX      =       Length of message to display
  2059. ;
  2060. ; OUTPUT:
  2061. ;       AX, CX contents destroyed.
  2062. ;
  2063. STAT_MSG        PROC                    ;
  2064.                 PUSH    DI              ;
  2065.                 PUSH    SI              ;
  2066.                 MOV     SI,AX           ; Location of message
  2067.                 MOV     AX,CX           ; Save count
  2068.                 MOV     DI,OFFSET STAT_Q ;
  2069.         REP     MOVSB                   ; Copy query to status
  2070.                 MOV     CX,Q_LNG        ; Clear rest of message area
  2071.                 SUB     CX,AX           ;
  2072.                 MOV     AL,' '          ;
  2073.         REP     STOSB                   ;
  2074.                 POP     SI              ;
  2075.                 POP     DI              ;
  2076.                 CALL    STATUS          ; Display message
  2077.                 RET                     ;
  2078. STAT_MSG        ENDP                    ;
  2079. ;
  2080. ;
  2081. ; PROCEDURE: STAT_CLR
  2082. ;
  2083. ; STAT_CLR clears the message area of the status line.
  2084. ;
  2085. ; INPUT:
  2086. ;       None
  2087. ;
  2088. ; OUTPUT:
  2089. ;       None
  2090. ;
  2091. STAT_CLR        PROC                    ;
  2092.                 PUSH    AX              ;
  2093.                 PUSH    CX              ;
  2094.                 PUSH    DI              ;
  2095.                 MOV     CX,Q_LNG        ;
  2096.                 MOV     DI,OFFSET STAT_Q ;
  2097.                 MOV     AL,' '          ;
  2098.         REP     STOSB                   ;
  2099.                 POP     DI              ;
  2100.                 POP     CX              ;
  2101.                 POP     AX              ;
  2102.                 RET                     ;
  2103. STAT_CLR        ENDP                    ;
  2104. ;
  2105. ;
  2106. ; PROCEDURE: GET_TIME
  2107. ;
  2108. ; GET_TIME gets the current date and time and edits the value to ASCII
  2109. ; characters and places the values in the date and time variables.
  2110. ;
  2111. ; INPUT:
  2112. ;       None
  2113. ;
  2114. ; OUTPUT:
  2115. ;       MONTH, MON, DOW, DAY, CENTURY, YEAR, HOUR, MINUTE, SECOND updated.
  2116. ;
  2117. GET_TIME        PROC                    ;
  2118. ;
  2119. ; Save registers used.
  2120. ;
  2121.                 PUSH    AX              ;
  2122.                 PUSH    CX              ;
  2123.                 PUSH    DX              ;
  2124. ;
  2125. ; Get date and convert to ASCII.
  2126. ;
  2127.                 MOV     AH,DATE$        ;
  2128.                 INT     DOS$            ; Get current date
  2129.                 MOV     AH,3            ; Convert DOW to an index
  2130.                 MUL     AH              ;
  2131.                 MOV     DOW,AX          ;
  2132. ;
  2133. ; Convert date to MM DD CC YY format.
  2134. ; Compute month table index.
  2135. ;
  2136.                 MOV     AL,DH           ; Month index
  2137.                 DEC     AL              ; Start index at 0
  2138.                 MOV     AH,3            ;
  2139.                 MUL     AH              ;
  2140.                 MOV     MON,AX          ;
  2141.                 MOV     AL,DH           ; Do month
  2142.                 CALL    BTD             ; Convert to ASCII
  2143.                 MOV     MONTH,AX        ;
  2144.                 MOV     AL,DL           ; Day
  2145.                 CALL    BTD             ;
  2146.                 MOV     DAY,AX          ;
  2147.                 MOV     AX,CX           ; Year
  2148.                 MOV     CL,100          ; Separate century
  2149.                 DIV     CL              ;
  2150.                 MOV     CL,AH           ; Save year
  2151.                 CALL    BTD             ;
  2152.                 MOV     CENTURY,AX      ; Century
  2153.                 MOV     AL,CL           ; Year
  2154.                 CALL    BTD             ;
  2155.                 MOV     YEAR,AX         ;
  2156. ;
  2157. ; Get time and convert to hh mm ss.
  2158. ;
  2159.                 MOV     AH,TIME$        ;
  2160.                 INT     DOS$            ; Get current time
  2161.                 MOV     AL,CH           ; Hour
  2162.                 CALL    BTD             ;
  2163.                 MOV     HOUR,AX         ;
  2164.                 MOV     AL,CL           ; Minutes
  2165.                 CALL    BTD             ;
  2166.                 MOV     MINUTE,AX       ;
  2167.                 ADD     DX,256-50       ; Round up seconds
  2168.                 MOV     AL,DH           ; Seconds
  2169.                 CALL    BTD             ;
  2170.                 MOV     SECOND,AX       ;
  2171.                 POP     DX              ;
  2172.                 POP     CX              ;
  2173.                 POP     AX              ;
  2174.                 RET                     ;
  2175. GET_TIME        ENDP                    ;
  2176. ;
  2177. ;
  2178. ; PROCEDURE BTD
  2179. ;
  2180. ; BTD converts a binary value from 00-99 to its decimal ASCII equivalent.
  2181. ;
  2182. ; INPUT:
  2183. ;       AL      =       Binary value
  2184. ;
  2185. ; OUTPUT:
  2186. ;       AX      =       ASCII value (low order in AH)
  2187. ;
  2188. BTD             PROC                    ;
  2189.                 XOR     AH,AH           ; Make a whole word
  2190.                 DIV     C10             ; Separate digits
  2191.                 ADD     AX,'00'         ; Convert to ASCII
  2192.                 RET                     ;
  2193. BTD             ENDP                    ;
  2194. ;
  2195. ;
  2196. ; PROCEDURE BTD3
  2197. ;
  2198. ; BTD3 converts a binary value from 000-999 to its decimal ASCII equivalent
  2199. ; and stores the result in a specified location.
  2200. ;
  2201. ; INPUT:
  2202. ;       AX      =       Value
  2203. ;       ES:DI   =       Location to save value
  2204. ;
  2205. ; OUTPUT:
  2206. ;       AX,DI contents destroyed.
  2207. ;
  2208. BTD3            PROC                    ;
  2209.                 DIV     C100            ; Isolate 100's digit
  2210.                 ADD     AL,"0"          ; Convert high order digit
  2211.                 STOSB                   ;
  2212.                 MOV     AL,AH           ;
  2213.                 CALL    BTD             ; Convert low order digits
  2214.                 STOSW                   ;
  2215.                 RET                     ;
  2216. BTD3            ENDP                    ;
  2217. ;
  2218. ;
  2219. ; PROCEDURE DTB
  2220. ;
  2221. ; DTB converts a sequence of decimal characters to their binary equivalent.
  2222. ; The resulting value must be <65536.
  2223. ;
  2224. ; INPUT:
  2225. ;       BX, CX, SI set up for GET_CHR
  2226. ;
  2227. ; OUTPUT:
  2228. ;       AL      =       Terminator character
  2229. ;       DX      =       Result value
  2230. ;
  2231. DTB             PROC                    ;
  2232.                 XOR     DX,DX           ; Zero accumulator
  2233. DTB_LP:                                 ;
  2234.                 CALL    GET_CHR         ; Get next character
  2235.                 JZ      DTB_END         ; No more characters
  2236.                 CMP     AL,'0'          ; Decimal character?
  2237.                 JB      DTB_END         ; No, end of conversion
  2238.                 CMP     AL,'9'          ;
  2239.                 JA      DTB_END         ;
  2240.                 SUB     AL,'0'          ; Convert to binary
  2241.                 PUSH    AX              ;
  2242.                 MOV     AX,DX           ;
  2243.                 MUL     WORD PTR C10    ; Multiply previous value
  2244.                 MOV     DX,AX           ;
  2245.                 POP     AX              ;
  2246.                 ADD     DL,AL           ;
  2247.                 ADC     DH,0            ;
  2248.                 JMP     DTB_LP          ; Keep accumulating value
  2249. DTB_END:                                ;
  2250.                 RET                     ;
  2251. DTB             ENDP                    ;
  2252. ;
  2253. ;
  2254. ; PROCEDURE GET_CHR
  2255. ;
  2256. ; GET_CHR returns the next character of the current file.  This may be either
  2257. ; the SCREEN file or the TEMPLATE file.  Once one file is read, it must be
  2258. ; read through to the end without referencing any other file.  The end of the
  2259. ; file will be signalled and the file closed when no more characters remain
  2260. ; in the file or the end-of-file sentinel character(26=1AH) is reached.
  2261. ;
  2262. ; INPUT:
  2263. ;       BX      =       File handle(SCREENFILE or TEMPLFILE)
  2264. ;       IN_CNT  =       Remaining characters in buffer
  2265. ;       IN_INDX =       Pointer to next character
  2266. ;
  2267. ; OUTPUT:
  2268. ;       AL      =       Character
  2269. ;       IN_CNT, IN_INDX updated
  2270. ;       ZF      =       1, end of file
  2271. ;
  2272. GET_CHR         PROC                    ;
  2273. ;
  2274. ; Check to see if any more characters remain
  2275. ;
  2276.                 CMP     IN_CNT,0        ; Any more in buffer
  2277.                 JZ      READ_MORE       ; No
  2278. ;
  2279. ; Get next character and return it.
  2280. ;
  2281.                 XCHG    SI,IN_INDX      ;
  2282.                 LODSB                   ;
  2283.                 XCHG    SI,IN_INDX      ;
  2284.                 DEC     IN_CNT          ; Decrement character count
  2285.                 CMP     AL,EOF_CHR      ; Is it end of file?
  2286.                 JE      FILE_DONE       ; Yes
  2287.                 RET                     ;
  2288. ;
  2289. ; Read next buffer full of file.
  2290. ;
  2291. READ_MORE:                              ;
  2292.                 PUSH    AX              ;
  2293.                 PUSH    CX              ;
  2294.                 PUSH    DX              ;
  2295.                 MOV     AH,RDFILE$      ;
  2296.                 MOV     CX,L_INB        ; Read all that buffer will hold
  2297.                 MOV     DX,OFFSET CHR_LOC ;
  2298.                 MOV     IN_INDX,DX      ;
  2299.                 INT     DOS$            ; Read file
  2300.                 MOV     IN_CNT,AX       ; Save amount read
  2301.                 POP     DX              ;
  2302.                 POP     CX              ;
  2303.                 POP     AX              ;
  2304.                 JC      SCRN_ERROR      ; Error reading file
  2305.                 CMP     IN_CNT,0        ; Any data read?
  2306.                 JNZ     GET_CHR         ; Read is OK, so return the character
  2307. FILE_DONE:                              ;
  2308.                 PUSHF                   ; Preserve carry flag
  2309.                 PUSH    AX              ;
  2310.                 MOV     AH,CLOSE$       ; Close the file
  2311.                 INT     DOS$            ;
  2312.                 POP     AX              ;
  2313.                 POPF                    ;
  2314.                 MOV     IN_CNT,1        ; Continue to signal EOF
  2315.                 MOV     IN_INDX,OFFSET CHR_LOC ;
  2316.                 MOV     CHR_LOC,EOF_CHR ;
  2317.                 XOR     AL,AL           ; Indicate end of file
  2318.                 RET                     ;
  2319. ;
  2320. ; Error reading screen file.
  2321. ;
  2322. SCRN_ERROR:                             ;
  2323.                 CMP     BX,SCREENFILE   ; Screen file?
  2324.                 JNE     TMPL_FAIL       ; No, template file
  2325.                 MOV     DX,OFFSET SCRN_ERR ;
  2326.                 MOV     CX,L_SERR       ;
  2327.                 JMP     ERROR_DSP       ;
  2328. ;
  2329. ; Error reading template file.
  2330. ;
  2331. TMPL_FAIL:                              ;
  2332.                 MOV     CX,L_TMPL       ;
  2333.                 MOV     DX,OFFSET TMPL_ERR ;
  2334.                 JMP     ERROR_DSP       ;
  2335. GET_CHR         ENDP                    ;
  2336. ;
  2337. ;
  2338. ; PROCEDURE OUT_CHR
  2339. ;
  2340. ; OUT_CHR sends one character to the output file.
  2341. ;
  2342. ; INPUT:
  2343. ;       AL      =       Character to send
  2344. ;
  2345. ; OUTPUT:
  2346. ;       None
  2347. ;
  2348. ; PROCEDURE WR_OUT
  2349. ;
  2350. ; WR_OUT writes any remaining buffered output to the output file.
  2351. ;
  2352. ; INPUT:
  2353. ;       None
  2354. ;
  2355. ; OUTPUT:
  2356. ;       None
  2357. ;
  2358. OUT_CHR         PROC                    ;
  2359. ;
  2360. ; Save registers used.
  2361. ;
  2362.                 PUSH    BX              ;
  2363. ;
  2364. ; Add character to buffer.  If buffer full, write to file.
  2365. ;
  2366.                 MOV     BX,OUT_INDX     ;
  2367.                 MOV     OUT_BUF[BX],AL  ;
  2368.                 INC     BX              ;
  2369.                 MOV     OUT_INDX,BX     ;
  2370.                 POP     BX              ;
  2371.                 CMP     BX,L_OUTB       ; Buffer full?
  2372.                 JAE     WR_OUT          ; Yes
  2373.                 RET                     ;
  2374. ;
  2375. ; Write data to out file.
  2376. ;
  2377. WR_OUT:                                 ;
  2378.                 PUSH    AX              ;
  2379.                 PUSH    BX              ;
  2380.                 PUSH    CX              ;
  2381.                 PUSH    DX              ;
  2382.                 MOV     CX,OUT_INDX     ; Amount to write
  2383.                 JCXZ    NO_OUT          ;
  2384.                 MOV     AH,WRFILE$      ;
  2385.                 MOV     BX,OUTFILE      ;
  2386.                 MOV     DX,OFFSET OUT_BUF ;
  2387.                 INT     DOS$            ; Write file
  2388.                 JC      OUT_ERR         ;
  2389. NO_OUT:                                 ;
  2390.                 POP     DX              ;
  2391.                 POP     CX              ;
  2392.                 POP     BX              ;
  2393.                 POP     AX              ;
  2394.                 RET                     ;
  2395. OUT_ERR:                                ;
  2396.                 MOV     CX,L_OUT        ;
  2397.                 MOV     DX,OFFSET OUT_MSG ;
  2398.                 JMP     ERROR_DSP       ;
  2399. OUT_CHR         ENDP                    ;
  2400. ;
  2401. ;
  2402. ; PROCEDURE DISP_SCREEN
  2403. ;
  2404. ; DISP_SCREEN redisplays the screen.
  2405. ; SCR_LIN*SCR_COL characters are displayed.
  2406. ;
  2407. ; If the show fields flag is set, new field definitions are indicated by
  2408. ; blinking []'s (║ if a single position) and constant area definitions
  2409. ; are indicated by blinking {}'s (╬ if a single position).
  2410. ;
  2411. ; INPUT:
  2412. ;       DI      =       Screen cursor position
  2413. ;       SI      =       Edit buffer cursor position
  2414. ;
  2415. ; OUTPUT:
  2416. ;       None
  2417. ;
  2418. DISP_SCREEN     PROC                    ;
  2419. ;
  2420. ; Save registers used.
  2421. ; Save current cursor position.
  2422. ;
  2423.                 PUSH    AX              ;
  2424.                 PUSH    DI              ;
  2425.                 PUSH    SI              ;
  2426. ;
  2427. ; Display characters until end of screen or buffer.
  2428. ;
  2429.                 SUB     SI,DI           ; Start of screen in edit buffer
  2430.                 XOR     DI,DI           ;
  2431. DISP_LP:                                ;
  2432.                 MOV     AL," "          ; Default space
  2433.                 MOV     AH,SCR_ATTR     ; Empty attribute
  2434.                 CMP     SI,EDIT_LAST    ; End of characters?
  2435.                 JA      NO_CHR          ; Yes
  2436.                 LODSW                   ; Get next char
  2437. NO_CHR:                                 ;
  2438.                 CALL    WRITE_SCREEN    ;
  2439.                 CMP     DI,DISP_SIZE    ; End of screen
  2440.                 JB      DISP_LP         ; No
  2441. ;
  2442. ; If the show fields flag is set, insert field indicator characters.
  2443. ;
  2444.                 CMP     SHOW,0          ; Showing definitions?
  2445.                 JZ      NO_SHOW         ; No
  2446.                 PUSH    BX              ;
  2447.                 XOR     BX,BX           ;
  2448.                 SUB     SI,DI           ; Back to start of screen
  2449. SHDF_LP:                                ; Do all input and constant definitions
  2450.                 MOV     AL,'['          ; Input definitions
  2451.                 MOV     DI,DEF_AREA[BX] ;
  2452.                 CALL    SHOW_IT         ; Start
  2453.                 MOV     AL,']'          ;
  2454.                 MOV     DI,DEF_AREA[BX+2] ;
  2455.                 DEC     DI              ;
  2456.                 DEC     DI              ;
  2457.                 CMP     DI,DEF_AREA[BX] ; Start and end the same?
  2458.                 JNE     NOT_DBL1        ;
  2459.                 MOV     AL,'║'          ;
  2460. NOT_DBL1:                               ;
  2461.                 CALL    SHOW_IT         ; End
  2462.                 MOV     AL,'{'          ; Constant definitions
  2463.                 MOV     DI,CONST_AREA[BX] ;
  2464.                 CALL    SHOW_IT         ; Start
  2465.                 MOV     AL,'}'          ;
  2466.                 MOV     DI,CONST_AREA[BX+2] ;
  2467.                 DEC     DI              ;
  2468.                 DEC     DI              ;
  2469.                 CMP     DI,CONST_AREA[BX] ; Start and end the same?
  2470.                 JNE     NOT_DBL2        ;
  2471.                 MOV     AL,'╬'          ;
  2472. NOT_DBL2:                               ;
  2473.                 CALL    SHOW_IT         ; End
  2474.                 ADD     BX,4            ;
  2475.                 CMP     BX,EDIT_FLD*4   ;
  2476.                 JB      SHDF_LP         ;
  2477. NO_CNDF:                                ;
  2478.                 POP     BX              ;
  2479. NO_SHOW:                                ;
  2480.                 POP     SI              ;
  2481.                 POP     DI              ;
  2482.                 POP     AX              ;
  2483.                 RET                     ;
  2484. ;
  2485. ; Check if on this screen and display if so.
  2486. ;
  2487. SHOW_IT:                                ;
  2488.                 CMP     DI,0            ; Definition present?
  2489.                 JZ      NOT_SH          ;
  2490.                 MOV     AH,[DI+1]       ; Get attribute
  2491.                 CMP     DI,SI           ; On this screen?
  2492.                 JB      NOT_SH          ; No
  2493.                 SUB     DI,SI           ; Offset to this one
  2494.                 CMP     DI,DISP_SIZE    ; On screen?
  2495.                 JAE     NOT_SH          ; No
  2496.                 OR      AH,80H          ; Set blink
  2497.                 CALL    WRITE_SCREEN    ; Display it
  2498. NOT_SH:                                 ;
  2499.                 RET                     ;
  2500. DISP_SCREEN     ENDP                    ;
  2501. ;
  2502. ;
  2503. ; PROCEDURE REST_VID
  2504. ;
  2505. ; REST_VID restores the screen as it was prior to doing the menu editing.
  2506. ;
  2507. ; INPUT:
  2508. ;       None
  2509. ;
  2510. ; OUTPUT:
  2511. ;       None
  2512. ;
  2513. REST_VID        PROC                    ;
  2514. ;
  2515. ; Save registers used.
  2516. ;
  2517.                 PUSH    AX              ;
  2518.                 PUSH    BX              ;
  2519.                 PUSH    DX              ;
  2520.                 PUSH    DI              ;
  2521.                 PUSH    SI              ;
  2522. ;
  2523. ; Restore video modes and screen.
  2524. ;
  2525.                 MOV     SI,DISP_LOC     ;
  2526.                 CMP     SI,0            ; Did we save the screen?
  2527.                 JZ      NO_REST         ; No
  2528.                 MOV     AX,WORD PTR SCR_COL ;
  2529.                 SHL     AX,1            ;
  2530.                 ADD     DISP_SIZE,AX    ; Include the last line
  2531.                 MOV     EDIT_LAST,-1    ; Make sure area considered in display
  2532.                 XOR     DI,DI           ; At top of screen
  2533.                 CALL    DISP_SCREEN     ; Redisplay the screen
  2534. NO_REST:                                ;
  2535.                 MOV     BH,SAVEPAGE     ;
  2536.                 MOV     AL,BH           ;
  2537.                 MOV     AH,PAGE$        ;
  2538.                 INT     VIDEO$          ;
  2539.                 MOV     DX,SAVECRS      ;
  2540.                 MOV     AH,CRS$         ;
  2541.                 INT     VIDEO$          ; Restore cursor position
  2542.                 POP     SI              ;
  2543.                 POP     DI              ;
  2544.                 POP     DX              ;
  2545.                 POP     BX              ;
  2546.                 POP     AX              ;
  2547.                 RET                     ;
  2548. REST_VID        ENDP                    ;
  2549. ;
  2550. ;
  2551. ; PROCEDURE: WRITE_SCREEN
  2552. ;
  2553. ; WRITE_SCREEN writes a character directly to the video refresh memory.
  2554. ;
  2555. ; INPUT:
  2556. ;       AX      =       Character and attribute to write
  2557. ;       DI      =       Location at which to write character
  2558. ;
  2559. ; OUTPUT:
  2560. ;       DI      =       DI + 2
  2561. ;
  2562. WRITE_SCREEN    PROC                    ;
  2563. ;
  2564. ; Compute video memory offset.
  2565. ;
  2566.                 PUSH    BX              ;
  2567.                 PUSH    DX              ;
  2568.                 PUSH    ES              ;
  2569.                 MOV     ES,VIDEO_SEG    ; Screen segment
  2570.                 ASSUME  ES:NOTHING      ;
  2571.                 CMP     FAST,0          ; Fast screen update?
  2572.                 JNZ     FAST_WRITE      ;
  2573.                 MOV     BX,AX           ;
  2574.                 MOV     DX,STATUS_REG   ; Retrieve status register.
  2575. HORZ_RET:                               ;
  2576.                 IN      AL,DX           ; Get status from adaptor
  2577.                 TEST    AL,1            ; Is it low?
  2578.                 JNZ     HORZ_RET        ; If not, wait until it is.
  2579.                 CLI                     ; No more interrupts.
  2580. WAIT_RET:                               ;
  2581.                 IN      AL,DX           ; Get status.
  2582.                 TEST    AL,1            ; Is it high?
  2583.                 JZ      WAIT_RET        ; If no, wait until it is.
  2584.                 MOV     AX,BX           ; Retrieve character; now it's OK
  2585. FAST_WRITE:                             ; Move the following code up
  2586.                 STOSW                   ; to write to screen buffer.
  2587.                 STI                     ; Interrupts back on.
  2588.                 POP     ES              ;
  2589.                 ASSUME  ES:CODE         ;
  2590.                 POP     DX              ;
  2591.                 POP     BX              ;
  2592.                 RET                     ;
  2593. WRITE_SCREEN    ENDP                    ;
  2594. ;
  2595. ;
  2596. ; PROCEDURE: TRIM
  2597. ;
  2598. ; TRIM determines the last non-blank character in an area on the screen.
  2599. ; Any location that contains the start or end of a defined input field is
  2600. ; also considered to be non-blank.
  2601. ; TRIM also considers a change in attribute value the equivalent of a non-blank.
  2602. ;
  2603. ; INPUT:
  2604. ;       DX      =       Start of area
  2605. ;       DI      =       End of area+2(i.e., location after end)
  2606. ;       AH      =       Attribute of preceding location
  2607. ;
  2608. ; OUTPUT:
  2609. ;       DI      =       Last non-blank(or attribute change)+2
  2610. ;       DI      =       DX, entire area blank
  2611. ;
  2612. TRIM            PROC                    ;
  2613.                 PUSH    AX              ;
  2614.                 PUSH    BX              ;
  2615.                 PUSH    CX              ;
  2616.                 MOV     AL,[DI-1]       ; Last attribute
  2617. TRIM_IT:                                ;
  2618.                 CMP     DX,DI           ; At start of area?
  2619.                 JE      TRIM_DONE       ; Yes, nothing to do
  2620.                 CMP     BYTE PTR [DI-2],' ' ; Blank?
  2621.                 JNE     TRIM_DONE       ; No, found end
  2622.                 LEA     CX,[DI-2]       ;
  2623.                 XOR     BX,BX           ;
  2624. TRIM_LP:                                ;
  2625.                 CMP     BX,DEF_NUM      ; Any more input fields?
  2626.                 JAE     TRIM_DF         ; No
  2627.                 CMP     CX,DEF_AREA[BX] ; Start of defined field?
  2628.                 JE      TRIM_DONE       ; Yes, in next position
  2629.                 CMP     DI,DEF_AREA[BX+2] ; End of defined field?
  2630.                 JE      TRIM_DONE       ; Yes
  2631.                 ADD     BX,4            ; Next definition
  2632.                 JMP     TRIM_LP         ;
  2633. TRIM_DF:                                ;
  2634.                 CMP     CX,DX           ; At first position?
  2635.                 JA      TRIM_CK         ; No
  2636.                 CMP     AH,[DI-1]       ; Is attribute different than entry?
  2637.                 JNE     TRIM_DONE       ; Yes
  2638.                 JMP     SHORT TRIM_NA   ;
  2639. TRIM_CK:                                ;
  2640.                 CMP     AL,[DI-3]       ; Does attribute change?
  2641.                 JNE     TRIM_DONE       ; Yes
  2642. TRIM_NA:                                ;
  2643.                 DEC     DI              ; Back up one
  2644.                 DEC     DI              ;
  2645.                 JMP     TRIM_IT         ;
  2646. TRIM_DONE:                              ;
  2647.                 POP     CX              ;
  2648.                 POP     BX              ;
  2649.                 POP     AX              ;
  2650.                 RET                     ;
  2651. TRIM            ENDP                    ;
  2652. ;
  2653. ;
  2654. ; PROCEDURE: TBL_SRCH
  2655. ;
  2656. ; TBL_SRCH searches a list of characters and returns the index*2 of any match
  2657. ; or 0 for no match.  The result value may be used to index a corresponding
  2658. ; table of word size values with the 0th entry being the no-match entry.
  2659. ;
  2660. ; INPUT:
  2661. ;       AL      =       Character to be matched
  2662. ;       CX      =       Length of table to search
  2663. ;       SI      =       Location of table to search
  2664. ;
  2665. ; OUTPUT:
  2666. ;       SI      =       0 if no match or index*2 of match
  2667. ;       CX contents are destroyed
  2668. ;
  2669. TBL_SRCH        PROC                    ;
  2670.                 PUSH    DI              ;
  2671.                 MOV     DI,SI           ; Table base
  2672.         REPNE   SCASB                   ; Search the table
  2673.                 JE      TBL_FND         ; If we found a match
  2674.                 MOV     DI,SI           ; So we generate a 0 result
  2675. TBL_FND:                                ;
  2676.                 SUB     SI,DI           ; Form index
  2677.                 NEG     SI              ;
  2678.                 SHL     SI,1            ; Double for word index
  2679.                 POP     DI              ;
  2680.                 RET                     ;
  2681. TBL_SRCH        ENDP                    ;
  2682. ;
  2683. ;
  2684. ; PROCEDURE: WTBL_SRCH
  2685. ;
  2686. ; WTBL_SRCH searches a list of words and returns the index of any match
  2687. ; or 0 for no match.  The result value may be used to index a corresponding
  2688. ; table of word size values with the 0th entry being the no-match entry.
  2689. ;
  2690. ; INPUT:
  2691. ;       AX      =       Word to be matched
  2692. ;       CX      =       Length of table to search
  2693. ;       SI      =       Location of table to search
  2694. ;
  2695. ; OUTPUT:
  2696. ;       SI      =       0 if no match or index of match
  2697. ;       CX contents are destroyed
  2698. ;
  2699. WTBL_SRCH       PROC                    ;
  2700.                 PUSH    DI              ;
  2701.                 MOV     DI,SI           ; Table base
  2702.         REPNE   SCASW                   ; Search the table
  2703.                 JE      WTBL_FND        ; If we found a match
  2704.                 MOV     DI,SI           ; So we generate a 0 result
  2705. WTBL_FND:                               ;
  2706.                 SUB     SI,DI           ; Form index
  2707.                 NEG     SI              ;
  2708.                 POP     DI              ;
  2709.                 RET                     ;
  2710. WTBL_SRCH       ENDP                    ;
  2711. ;
  2712. ;
  2713. ; PROCEDURE: FIELD_GEN
  2714. ;
  2715. ; FIELD_GEN is called when a screen file has been edited and is being output
  2716. ; to check for input and constant fields and insert the bracketing characters
  2717. ; as appropriate.
  2718. ;
  2719. ; INPUT:
  2720. ;       AL      =       '[' or ']' for start or end check
  2721. ;       DI      =       File index to check
  2722. ;
  2723. ; OUTPUT:
  2724. ;       None
  2725. ;
  2726. FIELD_GEN       PROC                    ;
  2727.                 PUSH    BX              ;
  2728. ;
  2729. ; Loop through field definitions.
  2730. ;
  2731.                 XOR     BX,BX           ; Check for start of input
  2732.                 CMP     AL,'['          ; Field start?
  2733.                 JE      FG_LP           ; Yes
  2734.                 INC     BX              ; Use end of field
  2735.                 INC     BX              ;
  2736. FG_LP:                                  ;
  2737.                 CMP     BX,DEF_NUM      ; Any more input fields?
  2738.                 JAE     NO_DEF          ; No
  2739.                 CMP     DI,DEF_AREA[BX] ; Start of field?
  2740.                 JNE     NO_DEF          ; Yes
  2741.                 CALL    OUT_CHR         ; Put start of input
  2742. NO_DEF:                                 ;
  2743.                 CMP     BX,CONST_NUM    ; Any more constant fields?
  2744.                 JAE     NO_CONST        ; No
  2745.                 CMP     DI,CONST_AREA[BX] ; Start of constant?
  2746.                 JNE     NO_CONST        ;
  2747.                 OR      AL,20H          ; Put start of constant
  2748.                 CALL    OUT_CHR         ;
  2749.                 AND     AL,NOT 20H      ;
  2750. NO_CONST:                               ;
  2751.                 ADD     BX,4            ;
  2752.                 CMP     BX,EDIT_FLD*4   ; Processed all possible fields?
  2753.                 JB      FG_LP           ;
  2754.                 POP     BX              ;
  2755.                 RET                     ;
  2756. FIELD_GEN       ENDP                    ;
  2757. ;
  2758. ; Location of reusable space.
  2759. ;
  2760. CHR_LOC         LABEL   BYTE            ; Input buffer
  2761. OUT_BUF         EQU     CHR_LOC+L_INB   ; Output I/O buffer
  2762. ;
  2763. ; Initialization data.
  2764. ;
  2765. ERROR_MSG       LABEL   BYTE            ;
  2766.                 DB      "MENU [/D/E/N] screen template out" ;
  2767. L_ERROR         EQU     $-ERROR_MSG     ;
  2768. OPT_CHR         LABEL   BYTE            ;
  2769.                 DB      'NDE'           ; Option letters
  2770. L_OPT           EQU     $-OPT_CHR       ;
  2771. OPT_VECT        LABEL   WORD            ;
  2772.                 DW      BAD_OPT         ;
  2773.                 DW      N_OPT           ;
  2774.                 DW      D_OPT           ;
  2775.                 DW      E_OPT           ;
  2776. ;
  2777. ;
  2778. ; INIT performs video and file initialization for MENU.  It is placed at the
  2779. ; end of the program area so that its space may be reused.
  2780. ;
  2781. INIT:                                   ;
  2782. ;
  2783. ; Find input file name and open it.
  2784. ;
  2785.                 MOV     SI,OFFSET P_CNT ;
  2786.                 LODSB                   ; Get count
  2787.                 XOR     AH,AH           ;
  2788.                 MOV     CX,AX           ;
  2789.                 XOR     AL,AL           ; Open for input only
  2790.                 XOR     BX,BX           ; Default to standard input or none
  2791.                 CALL    OPEN_FILE       ; Parse file name and open file
  2792.                 JC      ERROR_FILE      ; Error getting file
  2793.                 MOV     SCREENFILE,AX   ; Save handle
  2794.                 JMP     GET_TMPL        ;
  2795. ;
  2796. ; File does not exist.
  2797. ;
  2798. ERROR_FILE:                             ;
  2799.                 MOV     CX,L_ERROR      ;
  2800.                 MOV     DX,OFFSET ERROR_MSG ;
  2801.                 JMP     ERROR_DSP       ;
  2802. ;
  2803. ; Find template file name.
  2804. ;
  2805. GET_TMPL:                               ;
  2806.                 XOR     BX,BX           ;
  2807.                 XOR     AL,AL           ;
  2808.                 CALL    OPEN_FILE       ; Get template file
  2809.                 JC      ERROR_FILE      ;
  2810.                 MOV     TEMPLFILE,AX    ; Template handle
  2811. ;
  2812. ; Get output file name.
  2813. ;
  2814.                 MOV     BX,STDOUT       ; Default to standard output
  2815.                 MOV     AL,1            ; Open file for writing
  2816.                 CALL    OPEN_FILE       ;
  2817.                 JC      ERROR_FILE      ;
  2818.                 MOV     OUTFILE,AX      ; Output file handle
  2819. ;
  2820. ; See if multiple output files specified.
  2821. ;
  2822.                 MOV     DI,OFFSET OUT_HNDL ;
  2823. OUT_LP:                                 ;
  2824.                 STOSW                   ; Save handle in output table
  2825.                 INC     NUM_OUT         ; Increment count of output files
  2826. OUT_SKP:                                ;
  2827.                 JCXZ    CHECK_VOID      ; No more files, check void
  2828.                 MOV     AL,1            ; Create the file
  2829.                 CALL    OPEN_FILE       ;
  2830.                 JC      ERROR_FILE      ;
  2831.                 CMP     AX,STDOUT       ; Any file name there?
  2832.                 JNE     OUT_LP          ; Yes
  2833.                 JMP     OUT_SKP         ; No, skip saving handle
  2834. CHECK_VOID:                             ;
  2835.                 CMP     DOPT,L_DOPT     ; Only /D is legal
  2836.                 JE      CHECK_VID       ;
  2837.                 CMP     SCREENFILE,0    ; Any parameters?
  2838.                 JE      ERROR_FILE      ; No, error
  2839. ;
  2840. ; Determine current video modes and save them.
  2841. ;
  2842. CHECK_VID:                              ;
  2843.                 MOV     AX,BIOS_DATA    ; Point to the ROM BIOS data area
  2844.                 MOV     DS,AX           ; and get base address of active
  2845.                 ASSUME  DS:BIOS_DATA    ;
  2846.                 MOV     AX,ADDR_6845    ; display card.
  2847.                 PUSH    CS              ; Restore DS
  2848.                 POP     DS              ;
  2849.                 ASSUME  DS:CODE         ;
  2850.                 ADD     AX,6            ; Add six to get status register
  2851.                 MOV     STATUS_REG,AX   ; Store status register.
  2852.                 CMP     AX,3BAH         ; Status port of MONO card is 3BAH.
  2853.                 JE      MONO            ; If that's what we got, it's MONO
  2854.                 MOV     VIDEO_SEG,COLOR_SEG ; else COLOR so use that seg
  2855.                 MOV     AH,ALTSEL$      ; Try to select the EGA/VGA
  2856.                 MOV     BL,10H          ; Ask EGA/VGA for status
  2857.                 INT     VIDEO$          ;
  2858.                 CMP     BL,10H          ; EGA/VGA present?
  2859.                 JE      CGA             ; No, assume old CGA
  2860.                 MOV     AX,BIOS_DATA    ; There is an EGA/VGA.  Check if it is
  2861.                 MOV     DS,AX           ; the one we are using.
  2862.                 ASSUME  DS:BIOS_DATA    ;
  2863.                 MOV     AL,EGA_INFO     ; Get EGA/VGA status byte
  2864.                 PUSH    CS              ;
  2865.                 POP     DS              ;
  2866.                 ASSUME  DS:CODE         ;
  2867.                 TEST    AL,EGA_MASK     ; Is EGA/VGA active?
  2868.                 JNZ     CGA             ; No, do CGA initialization only
  2869. ;
  2870. ; Since it is an EGA/VGA, there may be other than 25 lines per screen.  Get the
  2871. ; actual number and change MENU to use it.
  2872. ;
  2873.                 XOR     BH,BH           ;
  2874.                 MOV     AX,EGASTAT$*256+48 ;
  2875.                 INT     VIDEO$          ; EGA/VGA get status
  2876.                 PUSH    CS              ;
  2877.                 POP     ES              ; Reset ES changed by VIDEO$
  2878.                 INC     DL              ; Number of lines
  2879.                 MOV     SCR_LIN,DL      ;
  2880. ;
  2881. ; For monochrome and EGA/VGA controllers, we do not need to wait for horizontal
  2882. ; retrace before putting a character on the display.
  2883. ;
  2884. MONO:                                   ; MDA or EGA/VGA
  2885.                 MOV     FAST,1          ; Set fast video flag
  2886. CGA:                                    ;
  2887.                 MOV     AH,VIDSTAT$     ; Get video state
  2888.                 INT     VIDEO$          ;
  2889.                 MOV     SCR_COL,AH      ; Save number of columns
  2890.                 MOV     SAVEPAGE,BH     ; Save current video page
  2891.                 CMP     AL,3            ; Check for legal video modes
  2892.                 JBE     VID_OK          ; OK
  2893.                 CMP     AL,7            ;
  2894.                 JE      VID_OK          ;
  2895.                 MOV     AH,SMODE$       ;
  2896.                 MOV     AL,3            ; Switch to standard text mode
  2897.                 INT     VIDEO$          ;
  2898.                 MOV     DISP_LOC,0      ; Don't try to save cleared screen
  2899.                 JMP     CHECK_VID       ; Get state again
  2900. VID_OK:                                 ;
  2901.                 MOV     AH,RDCRS$       ;
  2902.                 INT     VIDEO$          ; Save cursor position
  2903.                 MOV     SAVECRS,DX      ;
  2904.                 MOV     AL,SCR_LIN      ; Compute display area size
  2905.                 DEC     AL              ;
  2906.                 MUL     SCR_COL         ;
  2907.                 MOV     DISP_SIZE,AX    ;
  2908.                 SHL     DISP_SIZE,1     ; Room for attributes
  2909.                 ADD     AX,WORD PTR SCR_COL ;
  2910.                 INC     AX              ; Don't run right up to end
  2911.                 SHL     AX,1            ; Words
  2912.                 NEG     AX              ;
  2913.                 CMP     DISP_LOC,0      ; Are we saving the screen?
  2914.                 JNZ     SV_SCRN         ; Yes
  2915.                 XOR     AX,AX           ; No size required
  2916. SV_SCRN:                                ;
  2917.                 ADD     AX,SP           ; Subtract from size of program
  2918.                 SUB     AX,100H         ; Leave room for stack
  2919.                 CMP     DISP_LOC,0      ; Save screen?
  2920.                 JZ      NO_SVSCR        ; No
  2921.                 MOV     DISP_LOC,AX     ; Location of screen save area
  2922. NO_SVSCR:                               ;
  2923. ;
  2924. ; Initialize edit area to contain blanks.
  2925. ;
  2926.                 MOV     DI,OFFSET EDIT_LOC ;
  2927.                 SUB     AX,DI           ; Length of file area
  2928.                 SUB     AX,WORD PTR SCR_COL ; Leave pad for last line spaces
  2929.                 SHR     AX,1            ;
  2930.                 CWD                     ;
  2931.                 DIV     WORD PTR SCR_COL ; Make multiple of line length
  2932.                 MUL     WORD PTR SCR_COL ;
  2933.                 SHL     AX,1            ;
  2934.                 MOV     CX,AX           ;
  2935.                 ADD     AX,OFFSET EDIT_LOC-2 ;
  2936.                 MOV     EDIT_LAST,AX    ;
  2937.                 SHR     CX,1            ; Number of words
  2938.                 MOV     AL," "          ;
  2939.                 MOV     AH,SCR_ATTR     ;
  2940.         REP     STOSW                   ;
  2941. ;
  2942. ; Save current screen.
  2943. ;
  2944.                 CMP     DISP_LOC,0      ; Are we saving the screen?
  2945.                 JZ      NO_SCRN         ; No
  2946.                 XOR     AL,AL           ;
  2947.                 MOV     AH,PAGE$        ; Force page 0
  2948.                 INT     VIDEO$          ;
  2949.                 MOV     DI,DISP_LOC     ;
  2950.                 MOV     CX,DISP_SIZE    ;
  2951.                 SHR     CX,1            ;
  2952.                 ADD     CX,WORD PTR SCR_COL ; Full screen size
  2953.                 XOR     SI,SI           ; Start at top of screen
  2954. SAV_LP:                                 ;
  2955.                 CALL    READ_SCREEN     ;
  2956.                 STOSW                   ; Save
  2957.                 LOOP    SAV_LP          ;
  2958. NO_SCRN:                                ;
  2959.                 JMP     BEGIN           ; Start processing edit file
  2960. ;
  2961. ;
  2962. ; PROCEDURE: READ_SCREEN
  2963. ;
  2964. ; READ_SCREEN writes a character directly from the video refresh memory.
  2965. ;
  2966. ; INPUT:
  2967. ;       SI      =       Location in video refresh memory to read
  2968. ;
  2969. ; OUTPUT:
  2970. ;       AX      =       Character and attribute
  2971. ;       SI      =       SI + 2
  2972. ;       DX contents are destroyed.
  2973. ;
  2974. READ_SCREEN     PROC                    ;
  2975.                 PUSH    ES              ;
  2976.                 MOV     ES,VIDEO_SEG    ; Screen segment
  2977.                 ASSUME  ES:NOTHING      ;
  2978.                 CMP     FAST,0          ; Fast screen?
  2979.                 JNZ     FAST_READ       ; Yes
  2980. ;
  2981. ; Wait for horizontal retrace before reading.
  2982. ;
  2983.                 MOV     DX,STATUS_REG   ; Retrieve status register.
  2984. HORZ_RET2:                              ;
  2985.                 IN      AL,DX           ; Get status from adaptor
  2986.                 TEST    AL,1            ; Is it low?
  2987.                 JNZ     HORZ_RET2       ; If not, wait until it is.
  2988.                 CLI                     ; No more interrupts.
  2989. WAIT_RET2:                              ;
  2990.                 IN      AL,DX           ; Get status.
  2991.                 TEST    AL,1            ; Is it high?
  2992.                 JZ      WAIT_RET2       ; If no, wait until it is.
  2993. FAST_READ:                              ;
  2994.                 LODS    WORD PTR ES:[SI] ; to read to screen buffer.
  2995.                 STI                     ; Interrupts back on.
  2996.                 POP     ES              ;
  2997.                 ASSUME  ES:CODE         ;
  2998.                 RET                     ;
  2999. READ_SCREEN     ENDP                    ;
  3000. ;
  3001. ;
  3002. ; PROCEDURE OPEN_FILE
  3003. ;
  3004. ; OPEN_FILE parses the next file name in the parameter area and opens
  3005. ; the file.  If the file is opened for output only, the file is created.
  3006. ;
  3007. ; INPUT:
  3008. ;       AL      =       Open mode to use (0=read, 1=create, 2=update)
  3009. ;       BX      =       File handle to use if field missing
  3010. ;       CX      =       Remaining input character count
  3011. ;       SI      =       Next input character
  3012. ;
  3013. ; OUTPUT:
  3014. ;       AX      =       Return from OPEN (handle or error status)
  3015. ;       CF      =       1, error
  3016. ;       CX,SI   Updated
  3017. ;
  3018. OPEN_FILE       PROC                    ;
  3019. ;
  3020. ; Save registers used.
  3021. ;
  3022.                 PUSH    DX              ;
  3023.                 PUSH    AX              ;
  3024. ;
  3025. ; Find start of file name by skipping any white space characters.
  3026. ;
  3027. FIND_AGAIN:                             ;
  3028.                 JCXZ    MIS_FIL         ;
  3029. FIND_STRT:                              ;
  3030.                 LODSB                   ; Get next character
  3031.                 CMP     AL," "          ; Skip leading blanks/tabs
  3032.                 JE      SKIP_SEP        ;
  3033.                 CMP     AL,TAB_CHR      ;
  3034.                 JNE     STRT_FND        ; Found start of filename
  3035. SKIP_SEP:                               ;
  3036.                 LOOP    FIND_STRT       ;
  3037. MIS_FIL:                                ; Use default file handle
  3038.                 POP     AX              ;
  3039.                 POP     DX              ;
  3040.                 MOV     AX,BX           ;
  3041.                 CLC                     ;
  3042.                 RET                     ;
  3043. ;
  3044. ; Found start of file name.  Now find end.
  3045. ;
  3046. STRT_FND:                               ;
  3047.                 CMP     AL,'/'          ; Option?
  3048.                 JE      DO_OPT          ; Yes
  3049.                 LEA     DX,[SI-1]       ; Start of file name
  3050.                 JMP     SHORT CHK_FIL   ;
  3051. FIL_LP:                                 ;
  3052.                 LODSB                   ;
  3053. CHK_FIL:                                ;
  3054.                 CMP     AL," "          ;
  3055.                 JE      END_FIL         ; Found end of it
  3056.                 CMP     AL,","          ;
  3057.                 JE      END_FIL         ;
  3058.                 CMP     AL,TAB_CHR      ;
  3059.                 JE      END_FIL         ;
  3060.                 CMP     AL,CR_CHR       ;
  3061.                 JE      END_FIL         ;
  3062.                 LOOP    FIL_LP          ; Continue scanning
  3063.                 INC     SI              ;
  3064.                 INC     CX              ;
  3065. ;
  3066. ; Found end of file name.  Open file.
  3067. ;
  3068. END_FIL:                                ;
  3069.                 DEC     CX              ;
  3070.                 LEA     AX,[SI-1]       ; Ending location
  3071.                 CMP     AX,DX           ; No file?
  3072.                 JE      MIS_FIL         ; Yes, use default
  3073.                 MOV     BYTE PTR [SI-1],0 ; Make ASCIIZ
  3074.                 POP     AX              ; Open type
  3075.                 CMP     AL,1            ; Open for output only?
  3076.                 JE      CRE_FILE        ; Yes
  3077.                 MOV     AH,OPEN$        ;
  3078.                 INT     DOS$            ;
  3079.                 POP     DX              ;
  3080.                 RET                     ;
  3081. ;
  3082. ; Create a new file.
  3083. ;
  3084. CRE_FILE:                               ;
  3085.                 PUSH    CX              ;
  3086.                 XOR     CX,CX           ; Normal file type
  3087.                 MOV     AH,CREATE$      ; Create the file
  3088.                 INT     DOS$            ;
  3089.                 POP     CX              ;
  3090.                 POP     DX              ;
  3091.                 RET                     ;
  3092. ;
  3093. ; Check for /N = No_save_screen.
  3094. ;        or /D = Display only (Only ANSI sequences processed.)
  3095. ;        or /E = Edit screen file
  3096. ;
  3097. DO_OPT:                                 ;
  3098.                 DEC     CX              ;
  3099.                 JCXZ    MIS_FIL         ;
  3100.                 LODSB                   ; Get option letter
  3101.                 DEC     CX              ;
  3102.                 AND     AL,NOT 20H      ; Force to upper case
  3103.                 PUSH    CX              ;
  3104.                 PUSH    SI              ;
  3105.                 MOV     CX,L_OPT        ;
  3106.                 MOV     SI,OFFSET OPT_CHR ;
  3107.                 CALL    TBL_SRCH        ;
  3108.                 JMP     OPT_VECT[SI]    ; Switch on option
  3109. N_OPT:                                  ;
  3110.                 MOV     DISP_LOC,0      ; No screen save required
  3111. OK_OPT:                                 ;
  3112.                 POP     SI              ;
  3113.                 POP     CX              ;
  3114.                 JMP     FIND_AGAIN      ; Continue scanning
  3115. D_OPT:                                  ;
  3116.                 MOV     DOPT,L_DOPT     ; Display only, do not process
  3117.                 JMP     OK_OPT          ; control characters
  3118. E_OPT:                                  ;
  3119.                 MOV     EOPT,L_EDIT     ; Set edit flag
  3120.                 JMP     OK_OPT          ; Force display mode
  3121. BAD_OPT:                                ;
  3122.                 POP     SI              ;
  3123.                 POP     CX              ;
  3124.                 POP     AX              ;
  3125.                 POP     DX              ;
  3126.                 STC                     ; Error signal
  3127.                 RET                     ;
  3128. OPEN_FILE       ENDP                    ;
  3129. MENU            ENDP                    ;
  3130. EDIT_LOC        EQU     OUT_BUF+L_OUTB  ; Buffer for editing
  3131. CODE            ENDS                    ;
  3132.                 END     MENU            ;
  3133.